- fixed error notification not being dismissed and having a progress bar
- fixed editing filename template not using multiple copies of the same tag and writing at the cursor
- fixed appending search items in the search view not working for links
- fixed terminal removing any instance of yt-dlp in the command instead of just the beginning
- added ability to long press an item in the format details sheet to see the full string, and copy it/strings
- ellipsised really long titles and authors in history/download details bottom sheet
- now u can see all available piped instances in the piped instance dialog for you to choose
- removed really long format command and replaced them with -S format sorting
- fixed app not hiding adjust templates if user unchecked it
- added ability to show the command that was used in a history item, u can also see that in a queued,cancelled ... download
- Implemented preferred Audio Language. App will automatically choose an audio with your preference if it can find it, both in the download card also if you quick downloaded it
This commit is contained in:
zaednasr 2023-12-03 11:26:24 +01:00
parent a2369a85da
commit 19a52c13ec
No known key found for this signature in database
GPG key ID: 92B1DE23AD3D0E9E
60 changed files with 992 additions and 470 deletions

View file

@ -23,7 +23,7 @@ data class DownloadItem(
var container: String, var container: String,
@ColumnInfo(defaultValue = "") @ColumnInfo(defaultValue = "")
var downloadSections: String, var downloadSections: String,
val allFormats: MutableList<Format>, var allFormats: MutableList<Format>,
var downloadPath: String, var downloadPath: String,
var website: String, var website: String,
val downloadSize: String, val downloadSize: String,

View file

@ -25,5 +25,7 @@ data class Format(
@SerializedName(value = "asr", alternate = ["audioSampleRate"]) @SerializedName(value = "asr", alternate = ["audioSampleRate"])
var asr: String? = "", var asr: String? = "",
@SerializedName(value = "url") @SerializedName(value = "url")
var url: String? = "" var url: String? = "",
@SerializedName(value = "language", alternate = ["audioTrackLocale"])
val lang: String? = ""
) : Parcelable ) : Parcelable

View file

@ -45,13 +45,15 @@ class LogRepository(private val logDao: LogDao) {
val log = item.content ?: "" val log = item.content ?: ""
val lines = log.split("\n") val lines = log.split("\n")
//clean dublicate progress + add newline //clean dublicate progress + add newline
var newLine = line var newLine = line
if (newLine.contains("[download")){ if (newLine.contains("[download")){
newLine = "[download]" + line.split("[download]").last() newLine = "[download]" + line.split("[download]").last()
} }
val l = lines.dropLastWhile { it.contains("[download") }.joinToString("\n") + "\n${newLine}" val l = lines.dropLastWhile { it.contains("[download") }.joinToString("\n") + "\n${newLine}"
item.content = l item.content = l
//item.content += "\n$line"
logDao.update(item) logDao.update(item)
} }
} }

View file

@ -33,7 +33,10 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
if (resetResults) deleteAll() if (resetResults) deleteAll()
val res = infoUtil.search(inputQuery) val res = infoUtil.search(inputQuery)
itemCount.value = res.size itemCount.value = res.size
resultDao.insertMultiple(res) val ids = resultDao.insertMultiple(res)
ids.forEachIndexed { index, id ->
res[index]?.id = id
}
return res return res
} }
@ -46,7 +49,10 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
}else{ }else{
v.filter { it?.playlistTitle.isNullOrBlank() }.forEach { it?.playlistTitle = "ytdlnis-Search" } v.filter { it?.playlistTitle.isNullOrBlank() }.forEach { it?.playlistTitle = "ytdlnis-Search" }
} }
resultDao.insertMultiple(v) val ids = resultDao.insertMultiple(v)
ids.forEachIndexed { index, id ->
v[index]?.id = id
}
return ArrayList(v) return ArrayList(v)
} }
@ -66,7 +72,10 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
nextPageToken = tmpToken nextPageToken = tmpToken
} while (true) } while (true)
itemCount.value = items.size itemCount.value = items.size
resultDao.insertMultiple(items.toList()) val ids = resultDao.insertMultiple(items.toList())
ids.forEachIndexed { index, id ->
items[index]?.id = id
}
return items return items
} }
@ -79,7 +88,10 @@ class ResultRepository(private val resultDao: ResultDao, private val context: Co
}else{ }else{
items.filter { it?.playlistTitle.isNullOrBlank() }.forEach { it!!.playlistTitle = "ytdlnis-Search" } items.filter { it?.playlistTitle.isNullOrBlank() }.forEach { it!!.playlistTitle = "ytdlnis-Search" }
} }
resultDao.insertMultiple(items.toList()) val ids = resultDao.insertMultiple(items.toList())
ids.forEachIndexed { index, id ->
items[index]?.id = id
}
return items return items
} }

View file

@ -441,6 +441,13 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
val theFormats = formats.filter { it.format_note.contains("audio", ignoreCase = true) } val theFormats = formats.filter { it.format_note.contains("audio", ignoreCase = true) }
val requirements: MutableList<(Format) -> Boolean> = mutableListOf() val requirements: MutableList<(Format) -> Boolean> = mutableListOf()
requirements.add {it: Format -> audioFormatIDPreference.contains(it.format_id)} requirements.add {it: Format -> audioFormatIDPreference.contains(it.format_id)}
sharedPreferences.getString("audio_language", "")?.apply {
if (this.isNotEmpty()){
requirements.add { it: Format -> it.lang == this }
}
}
requirements.add {it: Format -> it.container == audioContainer } requirements.add {it: Format -> it.container == audioContainer }
requirements.add {it: Format -> "^(${audioCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.acodec)} requirements.add {it: Format -> "^(${audioCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.acodec)}
theFormats.maxByOrNull { f -> requirements.count{req -> req(f)} } ?: throw Exception() theFormats.maxByOrNull { f -> requirements.count{req -> req(f)} } ?: throw Exception()

View file

@ -23,6 +23,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.core.view.isVisible
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
@ -89,6 +90,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
private var shimmerCards: ShimmerFrameLayout? = null private var shimmerCards: ShimmerFrameLayout? = null
private var searchBar: SearchBar? = null private var searchBar: SearchBar? = null
private var searchView: SearchView? = null private var searchView: SearchView? = null
private var providersChipGroup: ChipGroup? = null
private var chipGroupDivider: View? = null
private var linkYouCopied: ConstraintLayout? = null private var linkYouCopied: ConstraintLayout? = null
private var queriesChipGroup: ChipGroup? = null private var queriesChipGroup: ChipGroup? = null
private var recyclerView: RecyclerView? = null private var recyclerView: RecyclerView? = null
@ -280,9 +283,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
} }
if (searchView?.currentTransitionState == SearchView.TransitionState.SHOWN){ if (searchView?.currentTransitionState == SearchView.TransitionState.SHOWN){
lifecycleScope.launch { updateSearchViewItems(searchView?.editText?.text, linkYouCopied)
updateSearchViewItems(searchView?.editText?.text, linkYouCopied)
}
} }
} }
@ -292,7 +293,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
val queriesInitStartBtn = queriesConstraint.findViewById<MaterialButton>(R.id.init_search_query) val queriesInitStartBtn = queriesConstraint.findViewById<MaterialButton>(R.id.init_search_query)
val isRightToLeft = resources.getBoolean(R.bool.is_right_to_left) val isRightToLeft = resources.getBoolean(R.bool.is_right_to_left)
val providersChipGroup = searchView!!.findViewById<ChipGroup>(R.id.providers) providersChipGroup = searchView!!.findViewById(R.id.providers)
val providers = resources.getStringArray(R.array.search_engines) val providers = resources.getStringArray(R.array.search_engines)
val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList() val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList()
@ -311,27 +312,27 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
} }
providersChipGroup!!.addView(tmp) providersChipGroup?.addView(tmp)
} }
val chipGroupDivider : View? = requireView().findViewById(R.id.chipGroupDivider) chipGroupDivider = requireView().findViewById(R.id.chipGroupDivider)
searchView!!.addTransitionListener { _, _, newState -> searchView!!.addTransitionListener { _, _, newState ->
if (newState == SearchView.TransitionState.SHOWN) { if (newState == SearchView.TransitionState.SHOWN) {
val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch") val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch")
providersChipGroup.children.forEach { providersChipGroup?.children?.forEach {
val tmp = providersChipGroup.findViewById<Chip>(it.id) val tmp = providersChipGroup?.findViewById<Chip>(it.id)
if (tmp.tag == currentProvider) { if (tmp?.tag?.equals(currentProvider) == true) {
tmp.isChecked = true tmp.isChecked = true
return@forEach return@forEach
} }
} }
if (Patterns.WEB_URL.matcher(searchBar!!.text.toString()).matches() && searchBar!!.text.isNotBlank()){ if (Patterns.WEB_URL.matcher(searchBar!!.text.toString()).matches() && searchBar!!.text.isNotBlank()){
providersChipGroup.visibility = GONE providersChipGroup?.visibility = GONE
chipGroupDivider?.visibility = GONE chipGroupDivider?.visibility = GONE
}else{ }else{
providersChipGroup.visibility = VISIBLE providersChipGroup?.visibility = VISIBLE
chipGroupDivider?.visibility = VISIBLE chipGroupDivider?.visibility = VISIBLE
} }
@ -371,9 +372,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
}else{ }else{
linkYouCopied!!.visibility = GONE linkYouCopied!!.visibility = GONE
} }
lifecycleScope.launch { updateSearchViewItems(searchView!!.editText.text, linkYouCopied)
updateSearchViewItems(searchView!!.editText.text, linkYouCopied)
}
}catch (e: Exception){ }catch (e: Exception){
e.printStackTrace() e.printStackTrace()
linkYouCopied!!.visibility = GONE linkYouCopied!!.visibility = GONE
@ -383,16 +382,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
searchView!!.editText.doAfterTextChanged { searchView!!.editText.doAfterTextChanged {
if (searchView!!.currentTransitionState != SearchView.TransitionState.SHOWN) return@doAfterTextChanged if (searchView!!.currentTransitionState != SearchView.TransitionState.SHOWN) return@doAfterTextChanged
lifecycleScope.launch { updateSearchViewItems(it, linkYouCopied)
updateSearchViewItems(it, linkYouCopied)
}
if (Patterns.WEB_URL.matcher(it.toString()).matches()){
providersChipGroup.visibility = GONE
chipGroupDivider?.visibility = GONE
}else{
providersChipGroup.visibility = VISIBLE
chipGroupDivider?.visibility = VISIBLE
}
} }
searchView!!.editText.setOnTouchListener(OnTouchListener { _, event -> searchView!!.editText.setOnTouchListener(OnTouchListener { _, event ->
@ -450,7 +440,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
queriesChipGroup!!.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> queriesChipGroup!!.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
if (queriesChipGroup!!.childCount == 0) queriesConstraint.visibility = GONE if (queriesChipGroup!!.childCount == 0) queriesConstraint.visibility = GONE
else queriesConstraint.visibility = VISIBLE else queriesConstraint.visibility = VISIBLE
searchView!!.editText.setText("")
} }
queriesInitStartBtn.setOnClickListener { queriesInitStartBtn.setOnClickListener {
@ -459,11 +448,15 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
} }
@SuppressLint("InflateParams") @SuppressLint("InflateParams")
private suspend fun updateSearchViewItems(searchQuery: Editable?, linkYouCopied: View?){ private fun updateSearchViewItems(searchQuery: Editable?, linkYouCopied: View?) = lifecycleScope.launch(Dispatchers.Main) {
searchSuggestionsLinearLayout!!.visibility = GONE searchSuggestionsLinearLayout!!.visibility = GONE
searchHistoryLinearLayout!!.visibility = GONE searchHistoryLinearLayout!!.visibility = GONE
searchSuggestionsLinearLayout!!.removeAllViews() searchSuggestionsLinearLayout!!.post {
searchHistoryLinearLayout!!.removeAllViews() searchSuggestionsLinearLayout!!.removeAllViews()
}
searchHistoryLinearLayout!!.post {
searchHistoryLinearLayout!!.removeAllViews()
}
linkYouCopied!!.visibility = GONE linkYouCopied!!.visibility = GONE
@ -472,76 +465,82 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
}else{ }else{
searchView!!.editText.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_plus, 0) searchView!!.editText.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_plus, 0)
} }
val suggestions = withContext(Dispatchers.IO){ val history = withContext(Dispatchers.IO){
resultViewModel.getSearchHistory().map { it.query }.filter { it.contains(searchQuery!!) } + resultViewModel.getSearchHistory().map { it.query }.filter { it.contains(searchQuery!!) }
if (sharedPreferences!!.getBoolean("search_suggestions", false)){
infoUtil!!.getSearchSuggestions(searchQuery.toString())
}else{
emptyList()
}
} }
val suggestions = if (sharedPreferences!!.getBoolean("search_suggestions", false)){
if (searchQuery!!.isEmpty()){ infoUtil!!.getSearchSuggestions(searchQuery.toString())
for (i in suggestions.indices) {
val v = LayoutInflater.from(fragmentContext)
.inflate(R.layout.search_suggestion_item, null)
val textView = v.findViewById<TextView>(R.id.suggestion_text)
textView.text = suggestions[i]
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_restore, 0, 0, 0)
Handler(Looper.getMainLooper()).post {
searchHistoryLinearLayout!!.addView(
v
)
}
textView.setOnClickListener {
searchView!!.setText(textView.text)
initSearch(searchView!!)
}
textView.setOnLongClickListener {
val deleteDialog = MaterialAlertDialogBuilder(requireContext())
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + textView.text + "\"!")
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
searchHistoryLinearLayout!!.removeView(v)
resultViewModel.removeSearchQueryFromHistory(textView.text.toString())
}
deleteDialog.show()
true
}
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener {
searchView!!.setText(textView.text)
searchView!!.editText.setSelection(searchView!!.editText.length())
}
}
searchHistoryLinearLayout!!.visibility = VISIBLE
if (linkYouCopied.findViewById<TextView>(R.id.suggestion_text).text.isNotEmpty()){
linkYouCopied.visibility = VISIBLE
}
}else{ }else{
for (i in suggestions.indices) { emptyList()
val v = LayoutInflater.from(fragmentContext)
.inflate(R.layout.search_suggestion_item, null)
val textView = v.findViewById<TextView>(R.id.suggestion_text)
textView.text = suggestions[i]
Handler(Looper.getMainLooper()).post {
searchSuggestionsLinearLayout!!.addView(
v
)
}
textView.setOnClickListener {
searchView!!.setText(textView.text)
initSearch(searchView!!)
}
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener {
searchView!!.setText(textView.text)
searchView!!.editText.setSelection(searchView!!.editText.length())
}
}
searchSuggestionsLinearLayout!!.visibility = VISIBLE
} }
history.forEach { s ->
val v = LayoutInflater.from(fragmentContext).inflate(R.layout.search_suggestion_item, null)
val textView = v.findViewById<TextView>(R.id.suggestion_text)
textView.text = s
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_restore, 0, 0, 0)
Handler(Looper.getMainLooper()).post {
searchHistoryLinearLayout!!.addView(
v
)
}
textView.setOnClickListener {
searchView!!.setText(s)
initSearch(searchView!!)
}
textView.setOnLongClickListener {
val deleteDialog = MaterialAlertDialogBuilder(requireContext())
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + s + "\"!")
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
searchHistoryLinearLayout!!.removeView(v)
resultViewModel.removeSearchQueryFromHistory(s)
}
deleteDialog.show()
true
}
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener {
searchView!!.editText.setText(s)
searchView!!.editText.setSelection(searchView!!.editText.length())
}
}
searchHistoryLinearLayout!!.isVisible = history.isNotEmpty()
if (linkYouCopied.findViewById<TextView>(R.id.suggestion_text).text.isNotEmpty()){
linkYouCopied.visibility = VISIBLE
}
suggestions.forEach { s ->
val v = LayoutInflater.from(fragmentContext)
.inflate(R.layout.search_suggestion_item, null)
val textView = v.findViewById<TextView>(R.id.suggestion_text)
textView.text = s
Handler(Looper.getMainLooper()).post {
searchSuggestionsLinearLayout!!.addView(
v
)
}
textView.setOnClickListener {
searchView!!.setText(s)
initSearch(searchView!!)
}
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener {
searchView!!.editText.setText(s)
searchView!!.editText.setSelection(searchView!!.editText.length())
}
}
searchSuggestionsLinearLayout!!.isVisible = suggestions.isNotEmpty()
if (Patterns.WEB_URL.matcher(searchView!!.editText.text).matches()){
providersChipGroup?.visibility = GONE
chipGroupDivider?.visibility = GONE
}else{
providersChipGroup?.visibility = VISIBLE
chipGroupDivider?.visibility = VISIBLE
}
} }
private fun initSearch(searchView: SearchView){ private fun initSearch(searchView: SearchView){

View file

@ -112,7 +112,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
val formatDetailsChip = card.findViewById<Chip>(R.id.format_note) val formatDetailsChip = card.findViewById<Chip>(R.id.format_note)
val sideDetails = mutableListOf<String>() val sideDetails = mutableListOf<String>()
sideDetails.add(item.format.format_note.uppercase()) sideDetails.add(item.format.format_note.uppercase().replace("\n", " "))
sideDetails.add(item.container.uppercase().ifEmpty { item.format.container.uppercase() }) sideDetails.add(item.container.uppercase().ifEmpty { item.format.container.uppercase() })
val fileSize = FileUtil.convertFileSize(item.format.filesize) val fileSize = FileUtil.convertFileSize(item.format.filesize)

View file

@ -14,12 +14,14 @@ import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView import android.widget.AutoCompleteTextView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.media3.common.util.Log
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
@ -205,19 +207,21 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
override fun onFormatsUpdated(allFormats: List<List<Format>>) { override fun onFormatsUpdated(allFormats: List<List<Format>>) {
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
resultItem?.formats?.removeAll(formats.toSet()) resultItem?.apply {
resultItem?.formats?.addAll(allFormats.first().filter { !genericAudioFormats.contains(it) }) this.formats.removeAll(formats.toSet())
if (resultItem != null){ this.formats.addAll(allFormats.first().filter { !genericAudioFormats.contains(it) })
resultViewModel.update(resultItem!!) resultViewModel.update(this)
kotlin.runCatching { kotlin.runCatching {
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
f1.updateUI(resultItem) f1.updateUI(this)
} }
} }
} }
formats = allFormats.first().filter { !genericAudioFormats.contains(it) }.toMutableList() formats = allFormats.first().filter { !genericAudioFormats.contains(it) }.toMutableList()
formats.removeAll(genericAudioFormats) formats.removeAll(genericAudioFormats)
val preferredFormat = downloadViewModel.getFormat(formats, Type.audio) val preferredFormat = downloadViewModel.getFormat(formats, Type.audio)
downloadItem.format = preferredFormat
downloadItem.allFormats = formats
UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, null) UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, null)
} }
} }

View file

@ -20,6 +20,7 @@ import android.widget.Toast
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.commit
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
@ -46,7 +47,6 @@ 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.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -417,65 +417,69 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
lifecycleScope.launch { lifecycleScope.launch {
resultViewModel.updatingData.collectLatest { resultViewModel.updatingData.collectLatest {
if (it){ kotlin.runCatching {
title.visibility = View.GONE if (it){
subtitle.visibility = View.GONE title.visibility = View.GONE
shimmerLoading.visibility = View.VISIBLE subtitle.visibility = View.GONE
shimmerLoadingSubtitle.visibility = View.VISIBLE shimmerLoading.visibility = View.VISIBLE
shimmerLoading.startShimmer() shimmerLoadingSubtitle.visibility = View.VISIBLE
shimmerLoadingSubtitle.startShimmer() shimmerLoading.startShimmer()
}else{ shimmerLoadingSubtitle.startShimmer()
title.visibility = View.VISIBLE }else{
subtitle.visibility = View.VISIBLE title.visibility = View.VISIBLE
shimmerLoading.visibility = View.GONE subtitle.visibility = View.VISIBLE
shimmerLoadingSubtitle.visibility = View.GONE shimmerLoading.visibility = View.GONE
shimmerLoading.stopShimmer() shimmerLoadingSubtitle.visibility = View.GONE
shimmerLoadingSubtitle.stopShimmer() shimmerLoading.stopShimmer()
shimmerLoadingSubtitle.stopShimmer()
}
} }
} }
} }
lifecycleScope.launch { lifecycleScope.launch {
resultViewModel.updatingFormats.collectLatest { resultViewModel.updatingFormats.collectLatest {
if (it){ kotlin.runCatching {
delay(500) if (it){
runCatching { delay(500)
val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment runCatching {
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply { val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment
isVisible = true f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply {
isClickable = true isVisible = true
setOnClickListener { isClickable = true
lifecycleScope.launch(Dispatchers.IO) { setOnClickListener {
resultViewModel.cancelUpdateFormatsItemData() lifecycleScope.launch(Dispatchers.IO) {
resultViewModel.cancelUpdateFormatsItemData()
}
} }
} }
} }
} runCatching {
runCatching { val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply {
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply { isVisible = true
isVisible = true isClickable = true
isClickable = true setOnClickListener {
setOnClickListener { lifecycleScope.launch(Dispatchers.IO) {
lifecycleScope.launch(Dispatchers.IO) { resultViewModel.cancelUpdateFormatsItemData()
resultViewModel.cancelUpdateFormatsItemData() }
} }
} }
} }
} }else{
}else{ runCatching {
runCatching { val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment
val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply {
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply { isVisible = false
isVisible = false isClickable = false
isClickable = false }
} }
} runCatching {
runCatching { val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply {
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.apply { isVisible = false
isVisible = false isClickable = false
isClickable = false }
} }
} }
} }
@ -485,47 +489,50 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
lifecycleScope.launch { lifecycleScope.launch {
resultViewModel.updateResultData.collectLatest { result -> resultViewModel.updateResultData.collectLatest { result ->
if (result == null) return@collectLatest if (result == null) return@collectLatest
lifecycleScope.launch(Dispatchers.Main) { kotlin.runCatching {
if (result.isNotEmpty()){ lifecycleScope.launch(Dispatchers.Main) {
if (result.size == 1 && result[0] != null){ if (result.isNotEmpty()){
fragmentAdapter.setResultItem(result[0]!!) if (result.size == 1 && result[0] != null){
runCatching { fragmentAdapter.setResultItem(result[0]!!)
val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment runCatching {
f.updateUI(result[0]) val f = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
} f.updateUI(result[0])
}
runCatching { runCatching {
val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment val f1 = fragmentManager?.findFragmentByTag("f1") as DownloadVideoFragment
f1.updateUI(result[0]) f1.updateUI(result[0])
} }
title.visibility = View.VISIBLE title.visibility = View.VISIBLE
subtitle.visibility = View.VISIBLE subtitle.visibility = View.VISIBLE
shimmerLoading.visibility = View.GONE shimmerLoading.visibility = View.GONE
shimmerLoadingSubtitle.visibility = View.GONE shimmerLoadingSubtitle.visibility = View.GONE
shimmerLoading.stopShimmer() shimmerLoading.stopShimmer()
shimmerLoadingSubtitle.stopShimmer() shimmerLoadingSubtitle.stopShimmer()
val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") } val usingGenericFormatsOrEmpty = result[0]!!.formats.isEmpty() || result[0]!!.formats.any { it.format_note.contains("ytdlnisgeneric") }
fragmentAdapter.setResultItem(result[0]!!) fragmentAdapter.setResultItem(result[0]!!)
arguments?.putParcelable("result", result[0]!!) arguments?.putParcelable("result", result[0]!!)
if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){ if (usingGenericFormatsOrEmpty && sharedPreferences.getBoolean("update_formats", false)){
initUpdateFormats(result[0]!!) initUpdateFormats(result[0]!!)
} }
}else{
//open multi download card instead
if (activity is ShareActivity){
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf(
Pair("results", result),
Pair("type", preferredType),
))
}else{ }else{
dismiss() //open multi download card instead
if (activity is ShareActivity){
val preferredType = DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!)
findNavController().navigate(R.id.action_downloadBottomSheetDialog_to_selectPlaylistItemsDialog, bundleOf(
Pair("results", result),
Pair("type", preferredType),
))
}else{
dismiss()
}
} }
} }
resultViewModel.updateResultData.emit(null)
} }
resultViewModel.updateResultData.emit(null)
} }
} }
} }
@ -533,40 +540,37 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
lifecycleScope.launch { lifecycleScope.launch {
resultViewModel.updateFormatsResultData.collectLatest { formats -> resultViewModel.updateFormatsResultData.collectLatest { formats ->
if (formats == null) return@collectLatest if (formats == null) return@collectLatest
lifecycleScope.launch { kotlin.runCatching {
withContext(Dispatchers.Main){ lifecycleScope.launch {
runCatching { withContext(Dispatchers.Main){
val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment runCatching {
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem) val f1 = fragmentManager.findFragmentByTag("f0") as DownloadAudioFragment
resultItem.formats = formats val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
fragmentAdapter.setResultItem(resultItem) resultItem.formats = formats
f1.updateUI(resultItem) fragmentAdapter.setResultItem(resultItem)
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE f1.updateUI(resultItem)
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
}
runCatching {
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
resultItem.formats = formats
fragmentAdapter.setResultItem(resultItem)
f1.updateUI(resultItem)
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
}
} }
runCatching {
val f1 = fragmentManager.findFragmentByTag("f1") as DownloadVideoFragment
val resultItem = downloadViewModel.createResultItemFromDownload(f1.downloadItem)
resultItem.formats = formats
fragmentAdapter.setResultItem(resultItem)
f1.updateUI(resultItem)
f1.view?.findViewById<LinearProgressIndicator>(R.id.format_loading_progress)?.visibility = View.GONE
}
}
if (formats.isNotEmpty()){ if (formats.isNotEmpty()){
result.formats = formats result.formats = formats
}
resultViewModel.updateFormatsResultData.emit(null)
} }
resultViewModel.updateFormatsResultData.emit(null)
} }
} }
} }
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
private fun getDownloadItem(selectedTabPosition: Int = tabLayout.selectedTabPosition) : DownloadItem{ private fun getDownloadItem(selectedTabPosition: Int = tabLayout.selectedTabPosition) : DownloadItem{
return when(selectedTabPosition){ return when(selectedTabPosition){
0 -> { 0 -> {
@ -614,21 +618,25 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
} }
private fun initUpdateData() { private fun initUpdateData() {
if (result.url.isBlank()) { kotlin.runCatching {
dismiss() if (result.url.isBlank()) {
return dismiss()
} return
if (resultViewModel.updatingData.value) return }
if (resultViewModel.updatingData.value) return
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
resultViewModel.updateItemData(result) resultViewModel.updateItemData(result)
}
} }
} }
private fun initUpdateFormats(res: ResultItem){ private fun initUpdateFormats(res: ResultItem){
if (resultViewModel.updatingFormats.value) return kotlin.runCatching {
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) { if (resultViewModel.updatingFormats.value) return
resultViewModel.updateFormatItemData(res) CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
resultViewModel.updateFormatItemData(res)
}
} }
} }
} }

View file

@ -66,7 +66,7 @@ class DownloadCommandFragment(private val resultItem: ResultItem? = null, privat
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java] commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
shownFields = preferences.getStringSet("modify_download_card", setOf())!!.toList().ifEmpty { requireContext().getStringArray(R.array.modify_download_card_values).toList() } shownFields = preferences.getStringSet("modify_download_card", requireContext().getStringArray(R.array.modify_download_card_values).toSet())!!.toList()
return fragmentView return fragmentView
} }

View file

@ -470,6 +470,13 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
} }
) )
bottomSheet.show() bottomSheet.show()
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
bottomSheet.behavior.peekHeight = displayMetrics.heightPixels
bottomSheet.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
} }
DownloadViewModel.Type.video -> { DownloadViewModel.Type.video -> {
val bottomSheet = BottomSheetDialog(requireContext()) val bottomSheet = BottomSheetDialog(requireContext())
@ -530,6 +537,13 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
) )
bottomSheet.show() bottomSheet.show()
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
bottomSheet.behavior.peekHeight = displayMetrics.heightPixels
bottomSheet.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
} }
DownloadViewModel.Type.command -> { DownloadViewModel.Type.command -> {
} }

View file

@ -223,13 +223,13 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
override fun onFormatsUpdated(allFormats: List<List<Format>>) { override fun onFormatsUpdated(allFormats: List<List<Format>>) {
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO){ withContext(Dispatchers.IO){
resultItem?.formats?.removeAll(formats) resultItem?.apply {
resultItem?.formats?.addAll(allFormats.first().filter { !genericVideoFormats.contains(it) }) this.formats.removeAll(formats)
if (resultItem != null){ this.formats.addAll(allFormats.first().filter { !genericVideoFormats.contains(it) })
resultViewModel.update(resultItem!!) resultViewModel.update(this)
kotlin.runCatching { kotlin.runCatching {
val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment val f1 = fragmentManager?.findFragmentByTag("f0") as DownloadAudioFragment
f1.updateUI(resultItem) f1.updateUI(this)
} }
} }
} }
@ -237,6 +237,8 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
formats = allFormats.first().filter { !genericVideoFormats.contains(it) }.toMutableList() formats = allFormats.first().filter { !genericVideoFormats.contains(it) }.toMutableList()
val preferredFormat = downloadViewModel.getFormat(formats, Type.video) val preferredFormat = downloadViewModel.getFormat(formats, Type.video)
val preferredAudioFormats = downloadViewModel.getPreferredAudioFormats(formats) val preferredAudioFormats = downloadViewModel.getPreferredAudioFormats(formats)
downloadItem.format = preferredFormat
downloadItem.allFormats = formats
UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, formats.filter { preferredAudioFormats.contains(it.format_id) }) UiUtil.populateFormatCard(requireContext(), formatCard, preferredFormat, formats.filter { preferredAudioFormats.contains(it.format_id) })
} }

View file

@ -11,23 +11,9 @@ class ProcessingSettingsFragment : BaseSettingsFragment() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.processing_preferences, rootKey) setPreferencesFromResource(R.xml.processing_preferences, rootKey)
val preferredVideoCodec : ListPreference? = findPreference("video_codec")
val preferredAudioCodec : ListPreference? = findPreference("audio_codec")
val preferredFormatID : EditTextPreference? = findPreference("format_id") val preferredFormatID : EditTextPreference? = findPreference("format_id")
val preferredFormatIDAudio : EditTextPreference? = findPreference("format_id_audio") val preferredFormatIDAudio : EditTextPreference? = findPreference("format_id_audio")
preferredVideoCodec?.summary = preferredVideoCodec?.entry
preferredVideoCodec?.setOnPreferenceChangeListener { preference, newValue ->
preferredVideoCodec.summary = preferredVideoCodec.entries[preferredVideoCodec.findIndexOfValue(newValue.toString())]
true
}
preferredAudioCodec?.summary = preferredAudioCodec?.entry
preferredAudioCodec?.setOnPreferenceChangeListener { preference, newValue ->
preferredAudioCodec.summary = preferredAudioCodec.entries[preferredAudioCodec.findIndexOfValue(newValue.toString())]
true
}
preferredFormatID?.title = "${getString(R.string.preferred_format_id)} [${getString(R.string.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)}]" preferredFormatID?.dialogTitle = "${getString(R.string.file_name_template)} [${getString(R.string.video)}]"

View file

@ -5,6 +5,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.util.UiUtil
import com.deniscerri.ytdlnis.util.UpdateUtil import com.deniscerri.ytdlnis.util.UpdateUtil
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDL
@ -63,6 +64,15 @@ class UpdateSettingsFragment : BaseSettingsFragment() {
true true
} }
val pipedInstance = findPreference<Preference>("piped_instance")
pipedInstance?.setOnPreferenceClickListener {
UiUtil.showPipedInstancesDialog(requireActivity(), preferences.getString("piped_instance", "")!!){
editor.putString("piped_instance", it)
editor.apply()
}
true
}
} }

View file

@ -202,7 +202,7 @@ class TerminalFragment : Fragment() {
showCancelFab() showCancelFab()
imm.hideSoftInputFromWindow(input?.windowToken, 0) imm.hideSoftInputFromWindow(input?.windowToken, 0)
lifecycleScope.launch { lifecycleScope.launch {
val command = input!!.text.toString().replace("yt-dlp", "") val command = input!!.text.toString().replaceFirst("yt-dlp", "")
downloadID = withContext(Dispatchers.IO){ downloadID = withContext(Dispatchers.IO){
terminalViewModel.insert(TerminalItem(command = command, log = output!!.text.toString())) terminalViewModel.insert(TerminalItem(command = command, log = output!!.text.toString()))
} }

View file

@ -98,12 +98,14 @@ object Extensions {
} }
fun File.getMediaDuration(context: Context): Int { fun File.getMediaDuration(context: Context): Int {
if (!exists()) return 0 return kotlin.runCatching {
val retriever = MediaMetadataRetriever() if (!exists()) return 0
retriever.setDataSource(context, Uri.parse(absolutePath)) val retriever = MediaMetadataRetriever()
val duration = retriever.extractMetadata(METADATA_KEY_DURATION) retriever.setDataSource(context, Uri.parse(absolutePath))
retriever.release() val duration = retriever.extractMetadata(METADATA_KEY_DURATION)
retriever.release()
return duration?.toIntOrNull()?.div(1000) ?: 0 duration?.toIntOrNull()?.div(1000) ?: 0
}.getOrElse { 0 }
} }
} }

View file

@ -10,6 +10,7 @@ import android.util.Patterns
import android.widget.Toast import android.widget.Toast
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.anggrayudi.storage.extension.count
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.ChapterItem import com.deniscerri.ytdlnis.database.models.ChapterItem
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.DownloadItem
@ -1045,13 +1046,11 @@ class InfoUtil(private val context: Context) {
request.addOption("--keep-fragments") request.addOption("--keep-fragments")
} }
val preferredAudioCodec = sharedPreferences.getString("audio_codec", "")!!
val aCodecPref = "ba[acodec~='^($preferredAudioCodec)']"
val embedMetadata = sharedPreferences.getBoolean("embed_metadata", true) val embedMetadata = sharedPreferences.getBoolean("embed_metadata", true)
var filenameTemplate = downloadItem.customFileNameTemplate var filenameTemplate = downloadItem.customFileNameTemplate
if(downloadItem.type != DownloadViewModel.Type.command){ if(downloadItem.type != DownloadViewModel.Type.command){
request.addOption("--trim-filenames", downDir.absolutePath.length + 117) request.addOption("--trim-filenames", 254 - downDir.absolutePath.length)
if (downloadItem.SaveThumb) { if (downloadItem.SaveThumb) {
request.addOption("--write-thumbnail") request.addOption("--write-thumbnail")
@ -1144,31 +1143,52 @@ class InfoUtil(private val context: Context) {
} }
} }
val preferredAudioCodec = sharedPreferences.getString("audio_codec", "")!!
val aCodecPrefIndex = context.getStringArray(R.array.audio_codec_values).indexOf(preferredAudioCodec)
val aCodecPref = context.getStringArray(R.array.audio_codec_values_ytdlp)[aCodecPrefIndex]
when(type){ when(type){
DownloadViewModel.Type.audio -> { DownloadViewModel.Type.audio -> {
val supportedContainers = context.resources.getStringArray(R.array.audio_containers) val supportedContainers = context.resources.getStringArray(R.array.audio_containers)
var audioQualityId : String = downloadItem.format.format_id var audioQualityId : String = downloadItem.format.format_id
if (audioQualityId.isBlank() || listOf("0", context.getString(R.string.best_quality), "best", "").contains(audioQualityId)){ if (audioQualityId.isBlank() || listOf("0", context.getString(R.string.best_quality), "ba", "best", "").contains(audioQualityId)){
audioQualityId = "" audioQualityId = ""
if (preferredAudioCodec.isNotBlank()){ }else if (listOf(context.getString(R.string.worst_quality), "wa", "worst").contains(audioQualityId)){
audioQualityId = "${aCodecPref}/bestaudio"
}
}else if (listOf(context.getString(R.string.worst_quality), "worst").contains(audioQualityId)){
audioQualityId = "worstaudio" audioQualityId = "worstaudio"
} }
val ext = downloadItem.container val ext = downloadItem.container
if (audioQualityId.isNotBlank()) request.addOption("-f", audioQualityId) if (audioQualityId.isNotBlank()) {
if (audioQualityId.contains("-") && !downloadItem.format.lang.isNullOrBlank() && downloadItem.format.lang != "None"){
audioQualityId = "ba[format_id~='^(${audioQualityId.split("-")[0]})'][language=${downloadItem.format.lang}]/ba/b"
}
request.addOption("-f", audioQualityId)
}else{
//enters here if generic or quick downloaded with ba format
val preferredLanguage = sharedPreferences.getString("audio_language","")!!
if (preferredLanguage.isNotBlank()){
request.addOption("-f", "ba[language=$preferredLanguage]/ba/b")
}
}
request.addOption("-x") request.addOption("-x")
val formatSorting = StringBuilder("hasaud")
if (aCodecPref.isNotBlank()){
formatSorting.append(",acodec:$aCodecPref")
}
if(ext.isNotBlank()){ if(ext.isNotBlank()){
if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex()) && supportedContainers.contains(ext)){ if(!ext.matches("(webm)|(Default)|(${context.getString(R.string.defaultValue)})".toRegex()) && supportedContainers.contains(ext)){
request.addOption("--audio-format", ext) request.addOption("--audio-format", ext)
formatSorting.append(",ext:$ext")
} }
} }
request.addOption("-P", downDir.absolutePath) request.addOption("-P", downDir.absolutePath)
request.addOption("-S", formatSorting.toString())
if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){ if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
request.addOption("--split-chapters") request.addOption("--split-chapters")
@ -1242,111 +1262,99 @@ class InfoUtil(private val context: Context) {
} }
//format logic //format logic
var videof = downloadItem.format.format_id var videoF = downloadItem.format.format_id
var audiof = "ba" var audioF = downloadItem.videoPreferences.audioFormatIDs.joinToString("+").ifBlank { "ba" }
if (downloadItem.videoPreferences.audioFormatIDs.isNotEmpty()){ val preferredAudioLanguage = sharedPreferences.getString("audio_language", "")!!
audiof = downloadItem.videoPreferences.audioFormatIDs.joinToString("+") if (downloadItem.videoPreferences.removeAudio) audioF = ""
}
if (downloadItem.videoPreferences.removeAudio) audiof = ""
val defaultFormats = context.resources.getStringArray(R.array.video_formats_values)
val usingGenericFormat = defaultFormats.contains(videof) || downloadItem.allFormats.isEmpty() || downloadItem.allFormats == getGenericVideoFormats(context.resources)
val f = StringBuilder() val f = StringBuilder()
if(!usingGenericFormat){ val defaultFormats = context.resources.getStringArray(R.array.video_formats_values)
if (audiof.isBlank()){ val usingGenericFormat = defaultFormats.contains(videoF) || downloadItem.allFormats.isEmpty() || downloadItem.allFormats == getGenericVideoFormats(context.resources)
f.append("$videof/bv/best") if (!usingGenericFormat){
}else{ if (audioF.isNotBlank()) audioF = "+$audioF"
f.append("$videof+$audiof/") f.append("$videoF$audioF/")
if (preferredAudioCodec.isNotBlank()) if (preferredAudioCodec.isNotBlank()){
f.append("$videof+$aCodecPref/") f.append("$videoF+$aCodecPref/")
f.append("$videof/best")
} }
f.append("$videoF/bv/b")
if (audiof.contains("+")){ if (audioF.count("+") > 1){
request.addOption("--audio-multistreams") request.addOption("--audio-multistreams")
} }
}else{ }else{
if (videof == context.resources.getString(R.string.best_quality) || videof == "best") { if (videoF == context.resources.getString(R.string.best_quality) || videoF == "best") {
videof = "bv" videoF = "bv"
}else if (videof == context.resources.getString(R.string.worst_quality) || videof == "worst") { }else if (videoF == context.resources.getString(R.string.worst_quality) || videoF == "worst") {
videof = "worst" videoF = "worst"
}else if (defaultFormats.contains(videof)) { }else if (defaultFormats.contains(videoF)) {
videof = "bv[height<="+videof.split("_")[0].dropLast(1)+"]" videoF = "bv[height<="+videoF.split("_")[0].dropLast(1)+"]"
} }
val preferredFormatIDs = sharedPreferences.getString("format_id", "").toString() val preferredFormatIDs = sharedPreferences.getString("format_id", "").toString()
.split(",") .split(",")
.filter { it.isNotEmpty() } .filter { it.isNotEmpty() }
.ifEmpty { listOf(videof) }.toMutableList() .ifEmpty { listOf(videoF) }.toMutableList()
if (!preferredFormatIDs.contains(videof)){ if (!preferredFormatIDs.contains(videoF)){
preferredFormatIDs.add(0, videof) preferredFormatIDs.add(0, videoF)
} }
// ^ [videoF, preferredID1, preferredID2...]
val preferredAudioFormatIDs = sharedPreferences.getString("format_id_audio", "") val preferredAudioFormatIDs = sharedPreferences.getString("format_id_audio", "")
.toString() .toString()
.split(",") .split(",")
.filter { it.isNotEmpty() } .filter { it.isNotBlank() }
.ifEmpty { .ifEmpty {
val list = mutableListOf<String>() val list = mutableListOf<String>()
if (preferredAudioCodec.isNotBlank()) list.add("ba[acodec~='^($preferredAudioCodec)']") if (preferredAudioCodec.isNotBlank()) list.add("ba[acodec~='^($preferredAudioCodec)']")
list.add(audiof) if (preferredAudioLanguage.isNotEmpty()) list.add("ba[language=$preferredAudioLanguage]")
list.add(audioF)
list list
} }.apply {
val preferredAudioFormats = if (downloadItem.videoPreferences.audioFormatIDs.isEmpty()) { }.toMutableList()
preferredAudioFormatIDs if (!preferredAudioFormatIDs.contains(audioF) && audioF != "ba"){
} else listOf(audiof) preferredAudioFormatIDs.add(0, audioF)
}
if (preferredAudioFormats.any{it.contains("+")}){ // ^ [audioF, preferredAID1, preferredAID2, ....]
if (preferredAudioFormatIDs.any{it.contains("+")}){
request.addOption("--audio-multistreams") request.addOption("--audio-multistreams")
} }
val preferredCodec = sharedPreferences.getString("video_codec", "") val preferredCodec = sharedPreferences.getString("video_codec", "")
val extPref = if (cont.isNotBlank()) "[ext=$cont]" else "" val vCodecPrefIndex = context.getStringArray(R.array.video_codec_values).indexOf(preferredCodec)
val vCodecPref = if (preferredCodec!!.isNotBlank()) "[vcodec~='^($preferredCodec)']" else "" val vCodecPref = context.getStringArray(R.array.video_codec_values_ytdlp)[vCodecPrefIndex]
preferredFormatIDs.forEach { v -> preferredFormatIDs.forEach { v ->
//build format with extension and vcodec preferredAudioFormatIDs.forEach { a ->
preferredAudioFormats.forEach { a ->
val aa = if (a.isNotBlank()) "+$a" else "" val aa = if (a.isNotBlank()) "+$a" else ""
f.append("$v$extPref$vCodecPref$aa/") f.append("$v$aa/")
} }
//build format with just videoformatid and audio if remove audio is not checked
//build format with vcodec
if (extPref.isNotBlank()){
preferredAudioFormats.forEach { a ->
val aa = if (a.isNotBlank()) "+$a" else ""
f.append("$v$vCodecPref$aa/")
}
}
//build format with audio
if (vCodecPref.isNotBlank()){
preferredAudioFormats.forEach {a ->
val aa = if (a.isNotBlank()) "+$a" else ""
f.append("$v$aa/")
}
}
if (!downloadItem.videoPreferences.removeAudio){ if (!downloadItem.videoPreferences.removeAudio){
//build format with audio with preferred language
if (preferredAudioLanguage.isNotBlank()){
val al = "$v+ba[language=$preferredAudioLanguage]/"
if (!f.contains(al)) f.append(al)
}
//build format with best audio //build format with best audio
if(!f.contains("$v+ba/")){ if (!f.contains("$v+ba/")) f.append("$v+ba/")
f.append("$v+ba/") //build format with standalone video
} f.append("$v/")
//build formats with standalone video
if(!f.contains("/$v/")){
f.append("$v/")
}
} }
} }
if(!f.endsWith("best/")){ if(!f.endsWith("b/")){
//last fallback //last fallback
f.append("best") f.append("b")
} }
val formatSorting = StringBuilder("+hasaud")
if (vCodecPref.isNotBlank()) formatSorting.append(",vcodec:$vCodecPref")
if (aCodecPref.isNotBlank()) formatSorting.append(",acodec:$aCodecPref")
if (cont.isNotBlank()) formatSorting.append(",ext:$cont")
request.addOption("-S", formatSorting.toString())
} }
@ -1404,6 +1412,18 @@ class InfoUtil(private val context: Context) {
return request return request
} }
fun getPipedInstances() : List<String> {
kotlin.runCatching {
val res = genericArrayRequest("https://piped-instances.kavin.rocks/")
val list = mutableListOf<String>()
for (i in 0 until res.length()) {
val element = res.getJSONObject(i)
list.add(element.getString("api_url"))
}
return list
}
return listOf()
}
fun parseYTDLRequestString(request : YoutubeDLRequest) : String { fun parseYTDLRequestString(request : YoutubeDLRequest) : String {
val arr = request.buildCommand().toMutableList() val arr = request.buildCommand().toMutableList()

View file

@ -35,6 +35,8 @@ class NotificationUtil(var context: Context) {
private val workerNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_WORKER_CHANNEL_ID) private val workerNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_WORKER_CHANNEL_ID)
private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID) private val commandDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID)
private val finishedDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_FINISHED_CHANNEL_ID) private val finishedDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_FINISHED_CHANNEL_ID)
private val erroredDownloadNotificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(context, DOWNLOAD_ERRORED_CHANNEL_ID)
private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java) private val notificationManager: NotificationManager = context.getSystemService(NotificationManager::class.java)
private val resources: Resources = context.resources private val resources: Resources = context.resources
@ -68,7 +70,7 @@ class NotificationUtil(var context: Context) {
channel.description = description channel.description = description
notificationManager.createNotificationChannel(channel) notificationManager.createNotificationChannel(channel)
//finished or errored downloads //finished downloads
name = resources.getString(R.string.finished_download_notification_channel_name) name = resources.getString(R.string.finished_download_notification_channel_name)
description = description =
resources.getString(R.string.finished_download_notification_channel_description) resources.getString(R.string.finished_download_notification_channel_description)
@ -76,7 +78,7 @@ class NotificationUtil(var context: Context) {
channel.description = description channel.description = description
notificationManager.createNotificationChannel(channel) notificationManager.createNotificationChannel(channel)
//finished or errored downloads //errored downloads
name = resources.getString(R.string.errored_downloads) name = resources.getString(R.string.errored_downloads)
description = description =
resources.getString(R.string.errored_download_notification_channel_description) resources.getString(R.string.errored_download_notification_channel_description)
@ -99,6 +101,7 @@ class NotificationUtil(var context: Context) {
COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder } COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID -> { return commandDownloadNotificationBuilder }
DOWNLOAD_FINISHED_CHANNEL_ID -> { return finishedDownloadNotificationBuilder } DOWNLOAD_FINISHED_CHANNEL_ID -> { return finishedDownloadNotificationBuilder }
DOWNLOAD_WORKER_CHANNEL_ID -> { return workerNotificationBuilder } DOWNLOAD_WORKER_CHANNEL_ID -> { return workerNotificationBuilder }
DOWNLOAD_ERRORED_CHANNEL_ID -> { return erroredDownloadNotificationBuilder }
} }
return downloadNotificationBuilder return downloadNotificationBuilder
} }
@ -554,11 +557,11 @@ class NotificationUtil(var context: Context) {
const val DOWNLOAD_MISC_CHANNEL_ID = "4" const val DOWNLOAD_MISC_CHANNEL_ID = "4"
const val DOWNLOAD_ERRORED_CHANNEL_ID = "6" const val DOWNLOAD_ERRORED_CHANNEL_ID = "6"
const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 3 const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 30000
const val DOWNLOAD_RESUME_NOTIFICATION_ID = 40000 const val DOWNLOAD_RESUME_NOTIFICATION_ID = 40000
const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 5 const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 50000
const val FORMAT_UPDATING_FINISHED_NOTIFICATION_ID = 7 const val DOWNLOAD_ERRORED_NOTIFICATION_ID = 60000
const val DOWNLOAD_ERRORED_NOTIFICATION_ID = 6 const val FORMAT_UPDATING_FINISHED_NOTIFICATION_ID = 70000
private const val PROGRESS_MAX = 100 private const val PROGRESS_MAX = 100
private const val PROGRESS_CURR = 0 private const val PROGRESS_CURR = 0

View file

@ -8,9 +8,6 @@ import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.OvalShape
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.text.Editable import android.text.Editable
@ -19,7 +16,6 @@ import android.text.format.DateFormat
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
@ -36,13 +32,12 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.isNotEmpty
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdlnis.database.models.CommandTemplate
@ -57,6 +52,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.ui.downloadcard.ConfigureDownloadBottomSheetDialog import com.deniscerri.ytdlnis.ui.downloadcard.ConfigureDownloadBottomSheetDialog
import com.deniscerri.ytdlnis.ui.downloadcard.VideoCutListener import com.deniscerri.ytdlnis.ui.downloadcard.VideoCutListener
import com.deniscerri.ytdlnis.util.Extensions.enableTextHighlight
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
@ -69,23 +65,19 @@ import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.materialswitch.MaterialSwitch import com.google.android.material.materialswitch.MaterialSwitch
import com.google.android.material.snackbar.Snackbar
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 com.neo.highlight.core.Highlight
import com.neo.highlight.util.listener.HighlightTextWatcher
import com.neo.highlight.util.scheme.ColorScheme
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import me.zhanghai.android.fastscroll.FastScrollerBuilder
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import java.util.regex.Pattern
object UiUtil { object UiUtil {
@ -481,10 +473,18 @@ object UiUtil {
val bottomSheet = BottomSheetDialog(context) val bottomSheet = BottomSheetDialog(context)
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE) bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
bottomSheet.setContentView(R.layout.history_item_details_bottom_sheet) bottomSheet.setContentView(R.layout.history_item_details_bottom_sheet)
val title = bottomSheet.findViewById<TextView>(R.id.bottom_sheet_title) bottomSheet.findViewById<TextView>(R.id.bottom_sheet_title)?.apply {
title!!.text = item.title.ifEmpty { "`${context.getString(R.string.defaultValue)}`" } text = item.title.ifEmpty { "`${context.getString(R.string.defaultValue)}`" }
val author = bottomSheet.findViewById<TextView>(R.id.bottom_sheet_author) setOnClickListener{
author!!.text = item.author.ifEmpty { "`${context.getString(R.string.defaultValue)}`" } showFullTextDialog(context, text.toString(), context.getString(R.string.title))
}
}
bottomSheet.findViewById<TextView>(R.id.bottom_sheet_author)?.apply {
text = item.author.ifEmpty { "`${context.getString(R.string.defaultValue)}`" }
setOnClickListener{
showFullTextDialog(context, text.toString(), context.getString(R.string.author))
}
}
// BUTTON ---------------------------------- // BUTTON ----------------------------------
val btn = bottomSheet.findViewById<FloatingActionButton>(R.id.download_button_type) val btn = bottomSheet.findViewById<FloatingActionButton>(R.id.download_button_type)
@ -507,6 +507,7 @@ object UiUtil {
val container = bottomSheet.findViewById<Chip>(R.id.container_chip) val container = bottomSheet.findViewById<Chip>(R.id.container_chip)
val codec = bottomSheet.findViewById<Chip>(R.id.codec) val codec = bottomSheet.findViewById<Chip>(R.id.codec)
val fileSize = bottomSheet.findViewById<Chip>(R.id.file_size) val fileSize = bottomSheet.findViewById<Chip>(R.id.file_size)
val command = bottomSheet.findViewById<Chip>(R.id.command)
when(status){ when(status){
DownloadRepository.Status.Queued, DownloadRepository.Status.QueuedPaused -> { DownloadRepository.Status.Queued, DownloadRepository.Status.QueuedPaused -> {
@ -527,9 +528,13 @@ object UiUtil {
} }
} }
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility = if (item.type != DownloadViewModel.Type.command){
View.GONE if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =
else formatNote!!.text = item.format.format_note View.GONE
else formatNote!!.text = item.format.format_note
}else{
formatNote?.isVisible = false
}
if (item.format.container != "") { if (item.format.container != "") {
container!!.text = item.format.container.uppercase() container!!.text = item.format.container.uppercase()
@ -557,6 +562,12 @@ object UiUtil {
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
else fileSize!!.text = fileSizeReadable else fileSize!!.text = fileSizeReadable
val infoUtil = InfoUtil(context)
command?.setOnClickListener {
showGeneratedCommand(context, infoUtil.parseYTDLRequestString(infoUtil.buildYoutubeDLRequest(item)))
}
val link = bottomSheet.findViewById<Button>(R.id.bottom_sheet_link) val link = bottomSheet.findViewById<Button>(R.id.bottom_sheet_link)
val url = item.url val url = item.url
link!!.text = url link!!.text = url
@ -631,16 +642,25 @@ object UiUtil {
val bottomSheet = BottomSheetDialog(context) val bottomSheet = BottomSheetDialog(context)
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE) bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
bottomSheet.setContentView(R.layout.history_item_details_bottom_sheet) bottomSheet.setContentView(R.layout.history_item_details_bottom_sheet)
val title = bottomSheet.findViewById<TextView>(R.id.bottom_sheet_title)
title!!.text = item!!.title bottomSheet.findViewById<TextView>(R.id.bottom_sheet_title)?.apply {
val author = bottomSheet.findViewById<TextView>(R.id.bottom_sheet_author) text = item!!.title
author!!.text = item.author setOnClickListener{
showFullTextDialog(context, text.toString(), context.getString(R.string.title))
}
}
bottomSheet.findViewById<TextView>(R.id.bottom_sheet_author)?.apply {
text = item!!.author
setOnClickListener{
showFullTextDialog(context, text.toString(), context.getString(R.string.author))
}
}
// BUTTON ---------------------------------- // BUTTON ----------------------------------
val btn = bottomSheet.findViewById<FloatingActionButton>(R.id.download_button_type) val btn = bottomSheet.findViewById<FloatingActionButton>(R.id.download_button_type)
val typeImageResource: Int = val typeImageResource: Int =
if (item.type == DownloadViewModel.Type.audio) { if (item!!.type == DownloadViewModel.Type.audio) {
if (isPresent) { if (isPresent) {
R.drawable.ic_music_downloaded R.drawable.ic_music_downloaded
} else { } else {
@ -668,6 +688,7 @@ object UiUtil {
val container = bottomSheet.findViewById<Chip>(R.id.container_chip) val container = bottomSheet.findViewById<Chip>(R.id.container_chip)
val codec = bottomSheet.findViewById<TextView>(R.id.codec) val codec = bottomSheet.findViewById<TextView>(R.id.codec)
val fileSize = bottomSheet.findViewById<TextView>(R.id.file_size) val fileSize = bottomSheet.findViewById<TextView>(R.id.file_size)
val command = bottomSheet.findViewById<Chip>(R.id.command)
val file = File(item.downloadPath) val file = File(item.downloadPath)
val calendar = Calendar.getInstance() val calendar = Calendar.getInstance()
@ -675,9 +696,13 @@ object UiUtil {
time!!.text = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(calendar.time) time!!.text = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(calendar.time)
time.isClickable = false time.isClickable = false
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility = if (item.type != DownloadViewModel.Type.command){
View.GONE if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =
else formatNote!!.text = item.format.format_note View.GONE
else formatNote!!.text = item.format.format_note
}else{
formatNote?.isVisible = false
}
if (item.format.container != "") { if (item.format.container != "") {
container!!.text = if (file.exists()) file.extension.uppercase() else item.format.container.uppercase() container!!.text = if (file.exists()) file.extension.uppercase() else item.format.container.uppercase()
@ -705,6 +730,11 @@ object UiUtil {
if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE if (fileSizeReadable == "?") fileSize!!.visibility = View.GONE
else fileSize!!.text = fileSizeReadable else fileSize!!.text = fileSizeReadable
command?.setOnClickListener {
showGeneratedCommand(context, item.command)
}
val link = bottomSheet.findViewById<Button>(R.id.bottom_sheet_link) val link = bottomSheet.findViewById<Button>(R.id.bottom_sheet_link)
val url = item.url val url = item.url
link!!.text = url link!!.text = url
@ -770,29 +800,44 @@ object UiUtil {
val fpsParent = bottomSheet.findViewById<ConstraintLayout>(R.id.fps_parent) val fpsParent = bottomSheet.findViewById<ConstraintLayout>(R.id.fps_parent)
val asrParent = bottomSheet.findViewById<ConstraintLayout>(R.id.asr_parent) val asrParent = bottomSheet.findViewById<ConstraintLayout>(R.id.asr_parent)
val clicker = View.OnClickListener {
copyToClipboard(((it as ConstraintLayout).getChildAt(1) as TextView).text.toString(), activity)
}
val longClicker = View.OnLongClickListener {
val txt = ((it as ConstraintLayout).getChildAt(1) as TextView).text.toString()
val snackbar = Snackbar.make(bottomSheet.findViewById(android.R.id.content)!!, txt, Snackbar.LENGTH_LONG)
snackbar.setAction(android.R.string.copy){
copyToClipboard(txt, activity)
}
val snackbarView: View = snackbar.view
val snackTextView = snackbarView.findViewById<View>(com.google.android.material.R.id.snackbar_text) as TextView
snackTextView.maxLines = 9999999
snackbar.show()
true
}
if (format.format_id.isBlank()) formatIdParent?.visibility = View.GONE if (format.format_id.isBlank()) formatIdParent?.visibility = View.GONE
else { else {
formatIdParent?.findViewById<TextView>(R.id.format_id_value)?.text = format.format_id formatIdParent?.findViewById<TextView>(R.id.format_id_value)?.text = format.format_id
formatIdParent?.setOnClickListener { formatIdParent?.setOnClickListener(clicker)
copyToClipboard(format.format_id, activity) formatIdParent?.setOnLongClickListener(longClicker)
}
} }
if (format.url.isNullOrBlank()) formatURLParent?.visibility = View.GONE if (format.url.isNullOrBlank()) formatURLParent?.visibility = View.GONE
else { else {
formatURLParent?.findViewById<TextView>(R.id.format_url_value)?.text = format.url formatURLParent?.findViewById<TextView>(R.id.format_url_value)?.text = format.url
formatURLParent?.setOnClickListener { formatURLParent?.setOnClickListener(clicker)
copyToClipboard(format.url!!, activity) formatURLParent?.setOnLongClickListener(longClicker)
}
} }
if (format.container.isBlank()) containerParent?.visibility = View.GONE if (format.container.isBlank()) containerParent?.visibility = View.GONE
else { else {
containerParent?.findViewById<TextView>(R.id.container_value)?.text = format.container containerParent?.findViewById<TextView>(R.id.container_value)?.text = format.container
containerParent?.setOnClickListener { containerParent?.setOnClickListener(clicker)
copyToClipboard(format.container, activity) containerParent?.setOnLongClickListener(longClicker)
}
} }
val codecField = val codecField =
@ -807,41 +852,36 @@ object UiUtil {
if (codecField.isBlank()) codecParent?.visibility = View.GONE if (codecField.isBlank()) codecParent?.visibility = View.GONE
else { else {
codecParent?.findViewById<TextView>(R.id.codec_value)?.text = codecField codecParent?.findViewById<TextView>(R.id.codec_value)?.text = codecField
codecParent?.setOnClickListener { codecParent?.setOnClickListener(clicker)
copyToClipboard(codecField, activity) codecParent?.setOnLongClickListener(longClicker)
}
} }
if (format.filesize != 0L) filesizeParent?.visibility = View.GONE if (format.filesize != 0L) filesizeParent?.visibility = View.GONE
else { else {
filesizeParent?.findViewById<TextView>(R.id.filesize_value)?.text = FileUtil.convertFileSize(format.filesize) filesizeParent?.findViewById<TextView>(R.id.filesize_value)?.text = FileUtil.convertFileSize(format.filesize)
filesizeParent?.setOnClickListener { filesizeParent?.setOnClickListener(clicker)
copyToClipboard(FileUtil.convertFileSize(format.filesize), activity) filesizeParent?.setOnLongClickListener(longClicker)
}
} }
if (format.format_note.isBlank()) formatnoteParent?.visibility = View.GONE if (format.format_note.isBlank()) formatnoteParent?.visibility = View.GONE
else { else {
formatnoteParent?.findViewById<TextView>(R.id.format_note_value)?.text = format.format_note formatnoteParent?.findViewById<TextView>(R.id.format_note_value)?.text = format.format_note
formatnoteParent?.setOnClickListener { formatnoteParent?.setOnClickListener(clicker)
copyToClipboard(format.format_note, activity) formatnoteParent?.setOnLongClickListener(longClicker)
}
} }
if (format.fps.isNullOrBlank() || format.fps == "0") fpsParent?.visibility = View.GONE if (format.fps.isNullOrBlank() || format.fps == "0") fpsParent?.visibility = View.GONE
else { else {
fpsParent?.findViewById<TextView>(R.id.fps_value)?.text = format.fps fpsParent?.findViewById<TextView>(R.id.fps_value)?.text = format.fps
fpsParent?.setOnClickListener { fpsParent?.setOnClickListener(clicker)
copyToClipboard(format.fps!!, activity) fpsParent?.setOnLongClickListener(longClicker)
}
} }
if (format.asr.isNullOrBlank()) asrParent?.visibility = View.GONE if (format.asr.isNullOrBlank()) asrParent?.visibility = View.GONE
else { else {
asrParent?.findViewById<TextView>(R.id.asr_value)?.text = format.asr asrParent?.findViewById<TextView>(R.id.asr_value)?.text = format.asr
asrParent?.setOnClickListener { asrParent?.setOnClickListener(clicker)
copyToClipboard(format.asr!!, activity) asrParent?.setOnLongClickListener(longClicker)
}
} }
@ -1627,12 +1667,9 @@ object UiUtil {
tmp.setOnClickListener { tmp.setOnClickListener {
val c = it as Chip val c = it as Chip
if(!c.isChecked){ val selectionStart = editText.selectionStart
editText.setText(editText.text.toString().replace(c.text.toString(), "")) editText.text.insert(selectionStart, c.text.toString())
editText.setSelection(editText.text.length) editText.setSelection(selectionStart + c.text.length)
}else{
editText.append(c.text)
}
} }
chips.add(tmp) chips.add(tmp)
@ -1643,9 +1680,138 @@ object UiUtil {
it.isChecked = editText.text.contains(it.text) it.isChecked = editText.text.contains(it.text)
chipGroup!!.addView(it) chipGroup!!.addView(it)
} }
editText.doOnTextChanged { text, start, before, count ->
chips.forEach {
it.isChecked = editText.text.contains(it.text)
}
}
} }
} }
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).gravity = Gravity.START dialog.getButton(AlertDialog.BUTTON_NEUTRAL).gravity = Gravity.START
} }
fun showPipedInstancesDialog(context: Activity, currentInstance: String, instanceSelected: (f: String) -> Unit){
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(context.getString(R.string.piped_instance))
val view = context.layoutInflater.inflate(R.layout.filename_template_dialog, null)
val editText = view.findViewById<EditText>(R.id.filename_edittext)
view.findViewById<TextInputLayout>(R.id.filename).hint = context.getString(R.string.piped_instance)
editText.setText(currentInstance)
editText.setSelection(editText.text.length)
builder.setView(view)
builder.setPositiveButton(
context.getString(R.string.ok)
) { _: DialogInterface?, _: Int ->
instanceSelected(editText.text.toString())
}
// handle the negative button of the alert dialog
builder.setNegativeButton(
context.getString(R.string.cancel)
) { _: DialogInterface?, _: Int -> }
builder.setNeutralButton("?") { _: DialogInterface?, _: Int ->
val browserIntent =
Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/TeamPiped/Piped/wiki/Instances"))
context.startActivity(browserIntent)
}
view.findViewById<View>(R.id.suggested).visibility = View.GONE
val dialog = builder.create()
dialog.show()
val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
editText!!.postDelayed({
editText.requestFocus()
imm.showSoftInput(editText, 0)
}, 300)
//handle suggestion chips
CoroutineScope(Dispatchers.IO).launch {
val chipGroup = view.findViewById<ChipGroup>(R.id.filename_suggested_chipgroup)
val chips = mutableListOf<Chip>()
val instances = InfoUtil(context).getPipedInstances()
instances.forEach { s ->
val tmp = context.layoutInflater.inflate(R.layout.filter_chip, chipGroup, false) as Chip
tmp.text = s
tmp.setOnClickListener {
val c = it as Chip
c.toggle()
editText.setText(c.text.toString())
editText.setSelection(c.text.length)
}
chips.add(tmp)
}
withContext(Dispatchers.Main){
view.findViewById<View>(R.id.suggested).visibility = View.VISIBLE
chips.forEach {
it.isChecked = editText.text.contains(it.text)
chipGroup!!.addView(it)
}
editText.doOnTextChanged { text, start, before, count ->
chips.forEach {
it.isChecked = editText.text == it.text
}
}
}
}
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).gravity = Gravity.START
}
private fun showGeneratedCommand(context: Activity, command: String){
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(context.getString(R.string.command))
val view = context.layoutInflater.inflate(R.layout.command_dialog, null)
val text = view.findViewById<TextView>(R.id.commandText)
text.text = command
text.isLongClickable = true
text.setTextIsSelectable(true)
text.enableTextHighlight()
builder.setView(view)
builder.setPositiveButton(
context.getString(android.R.string.copy)
) { _: DialogInterface?, _: Int ->
copyToClipboard(command, context)
}
// handle the negative button of the alert dialog
builder.setNegativeButton(
context.getString(R.string.cancel)
) { _: DialogInterface?, _: Int -> }
val dialog = builder.create()
dialog.show()
}
private fun showFullTextDialog(context: Activity, txt: String, title: String){
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(title)
val view = context.layoutInflater.inflate(R.layout.command_dialog, null)
val text = view.findViewById<TextView>(R.id.commandText)
text.text = txt
text.isLongClickable = true
text.setTextIsSelectable(true)
builder.setView(view)
builder.setPositiveButton(
context.getString(android.R.string.copy)
) { _: DialogInterface?, _: Int ->
copyToClipboard(txt, context)
}
// handle the negative button of the alert dialog
builder.setNegativeButton(
context.getString(R.string.cancel)
) { _: DialogInterface?, _: Int -> }
val dialog = builder.create()
dialog.show()
}
} }

View file

@ -91,9 +91,8 @@ class TerminalDownloadWorker(
val logItem = LogItem( val logItem = LogItem(
0, 0,
"Terminal Download", "Terminal Task",
"Downloading:\n" + "Terminal Task\n" +
"Terminal Download\n" +
"Command: ${command}\n\n", "Command: ${command}\n\n",
Format(), Format(),
DownloadViewModel.Type.command, DownloadViewModel.Type.command,

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/commandText"
android:layout_width="match_parent"
android:focusable="true"
android:clickable="true"
android:textIsSelectable="true"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -31,7 +31,8 @@
android:id="@+id/bottom_sheet_title" android:id="@+id/bottom_sheet_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/app_name" android:maxLines="3"
android:ellipsize="end"
android:textColor="?attr/colorOnSurface" android:textColor="?attr/colorOnSurface"
android:textSize="25sp" /> android:textSize="25sp" />
@ -40,7 +41,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="5dp" android:paddingTop="5dp"
android:text="@string/app_name" android:maxLines="2"
android:ellipsize="end"
android:textSize="15sp" /> android:textSize="15sp" />
</LinearLayout> </LinearLayout>
@ -139,6 +141,20 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.chip.Chip
android:id="@+id/command"
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:minWidth="30dp"
app:cornerRadius="10dp"
android:text="@string/command"
app:chipIcon="@drawable/ic_baseline_keyboard_arrow_right_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
</HorizontalScrollView> </HorizontalScrollView>

View file

@ -32,7 +32,7 @@
<string name="version">الإصدار</string> <string name="version">الإصدار</string>
<string name="update_app">التحقق من وجود تحديثات</string> <string name="update_app">التحقق من وجود تحديثات</string>
<string name="command_directory">مجلد الأوامر المخصصة</string> <string name="command_directory">مجلد الأوامر المخصصة</string>
<string name="couldnt_find_apk">لم يتم العثور على APK صالح.</string> <string name="couldnt_find_apk">لم يتم العثور على APK صالح</string>
<string name="best_quality">أفضل جودة متاحة</string> <string name="best_quality">أفضل جودة متاحة</string>
<string name="downloading">التحميل</string> <string name="downloading">التحميل</string>
<string name="limit_rate">حد السرعة</string> <string name="limit_rate">حد السرعة</string>

View file

@ -14,7 +14,7 @@
<string name="update_ytdl">yt-dlp yeni versiyasın quraşdır</string> <string name="update_ytdl">yt-dlp yeni versiyasın quraşdır</string>
<string name="source_code">Mənbə Kodu</string> <string name="source_code">Mənbə Kodu</string>
<string name="search_hint">Axtar və ya URL Əlavə Et</string> <string name="search_hint">Axtar və ya URL Əlavə Et</string>
<string name="failed_download">Faylı yükləmək mümkün olmadı.</string> <string name="failed_download">Faylı yükləmək mümkün olmadı</string>
<string name="download_notification_channel_name">Fayl Yükləmələri</string> <string name="download_notification_channel_name">Fayl Yükləmələri</string>
<string name="download_notification_channel_description">Səs və video faylların yüklənilmə irəliləyişin göstərən bildiriş</string> <string name="download_notification_channel_description">Səs və video faylların yüklənilmə irəliləyişin göstərən bildiriş</string>
<string name="you_are_in_latest_version">Ən son versiya işlədilir</string> <string name="you_are_in_latest_version">Ən son versiya işlədilir</string>
@ -32,7 +32,7 @@
<string name="update_app">Yeniləmələr üçün yoxla</string> <string name="update_app">Yeniləmələr üçün yoxla</string>
<string name="version">Versiya</string> <string name="version">Versiya</string>
<string name="command_directory">Şəxsi Əmr Qovluğu</string> <string name="command_directory">Şəxsi Əmr Qovluğu</string>
<string name="couldnt_find_apk">Uyğun APK tapılmadı.</string> <string name="couldnt_find_apk">Uyğun APK tapılmadı</string>
<string name="downloading_update">Yeni versiya yüklənilir</string> <string name="downloading_update">Yeni versiya yüklənilir</string>
<string name="audio">Səs</string> <string name="audio">Səs</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -5,7 +5,7 @@
<string name="download_notification_channel_name">Preuzimanja fajlova</string> <string name="download_notification_channel_name">Preuzimanja fajlova</string>
<string name="update_ytdl">Instaliraj novu verziju yt-dlp(a)</string> <string name="update_ytdl">Instaliraj novu verziju yt-dlp(a)</string>
<string name="source_code">Izvorni kod</string> <string name="source_code">Izvorni kod</string>
<string name="failed_download">Ne može se preuzeti fajl.</string> <string name="failed_download">Ne može se preuzeti fajl</string>
<string name="search">Pretraga</string> <string name="search">Pretraga</string>
<string name="remove_all">Ukloniti sve</string> <string name="remove_all">Ukloniti sve</string>
<string name="remove_results">Obriši rezultate</string> <string name="remove_results">Obriši rezultate</string>

View file

@ -12,7 +12,7 @@
<string name="updating">Aktualizuji</string> <string name="updating">Aktualizuji</string>
<string name="home">Domů</string> <string name="home">Domů</string>
<string name="remove_results">Odstranit výsledky</string> <string name="remove_results">Odstranit výsledky</string>
<string name="failed_download">Soubor se nepodařilo stáhnout.</string> <string name="failed_download">Soubor se nepodařilo stáhnout</string>
<string name="search">Hledat</string> <string name="search">Hledat</string>
<string name="settings">Nastavení</string> <string name="settings">Nastavení</string>
<string name="worst_quality">Nejhorší kvalita</string> <string name="worst_quality">Nejhorší kvalita</string>
@ -24,7 +24,7 @@
<string name="cancel_download">Zrušit stahování</string> <string name="cancel_download">Zrušit stahování</string>
<string name="audio_quality">Kvalita audia</string> <string name="audio_quality">Kvalita audia</string>
<string name="audio_format">Audio formát</string> <string name="audio_format">Audio formát</string>
<string name="couldnt_find_apk">Nepodařilo se najít vhodný APK soubor.</string> <string name="couldnt_find_apk">Nepodařilo se najít vhodný APK soubor</string>
<string name="ytdl_updating_started">Stahování nové verze</string> <string name="ytdl_updating_started">Stahování nové verze</string>
<string name="command_download_notification_channel_description">Upozornění ukazující stahování za pomoci yt-dlp příkazu</string> <string name="command_download_notification_channel_description">Upozornění ukazující stahování za pomoci yt-dlp příkazu</string>
<string name="add_chapters">Kapitoly ve videích</string> <string name="add_chapters">Kapitoly ve videích</string>

View file

@ -27,7 +27,7 @@
<string name="update_app">Nach Aktualisierungen suchen</string> <string name="update_app">Nach Aktualisierungen suchen</string>
<string name="version">Version</string> <string name="version">Version</string>
<string name="command_directory">Benutzerdefinierter Befehlsordner</string> <string name="command_directory">Benutzerdefinierter Befehlsordner</string>
<string name="couldnt_find_apk">Es konnte keine passende APK gefunden werden.</string> <string name="couldnt_find_apk">Es konnte keine passende APK gefunden werden</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>
<string name="add_chapters_summary">Markiere YouTube-/SponsorBlock-Segmente als Kapitel für das Video</string> <string name="add_chapters_summary">Markiere YouTube-/SponsorBlock-Segmente als Kapitel für das Video</string>
@ -61,7 +61,7 @@
<string name="delete_files_too">Lösche die Dateien vom Gerät</string> <string name="delete_files_too">Lösche die Dateien vom Gerät</string>
<string name="search">Suchen</string> <string name="search">Suchen</string>
<string name="home">Startseite</string> <string name="home">Startseite</string>
<string name="failed_download">Datei konnte nicht heruntergeladen werden.</string> <string name="failed_download">Datei konnte nicht heruntergeladen werden</string>
<string name="download_notification_channel_name">Datei-Downloads</string> <string name="download_notification_channel_name">Datei-Downloads</string>
<string name="you_are_in_latest_version">Du verwendest die neueste Version</string> <string name="you_are_in_latest_version">Du verwendest die neueste Version</string>
<string name="downloading_update">Neuste Version wird heruntergeladen</string> <string name="downloading_update">Neuste Version wird heruntergeladen</string>

View file

@ -127,7 +127,7 @@
<string name="about">Περί</string> <string name="about">Περί</string>
<string name="source_code">Πηγαίος Κώδικας</string> <string name="source_code">Πηγαίος Κώδικας</string>
<string name="search_hint">Αναζήτηση ή Εισαγωγή URL</string> <string name="search_hint">Αναζήτηση ή Εισαγωγή URL</string>
<string name="failed_download">Αδύνατη η λήψη του αρχείου.</string> <string name="failed_download">Αδύνατη η λήψη του αρχείου</string>
<string name="download_notification_channel_name">Λήψεις Αρχείων</string> <string name="download_notification_channel_name">Λήψεις Αρχείων</string>
<string name="download_notification_channel_description">Ειδοποίηση που δείχνει την πρόοδο της λήψης αρχείων ήχου και εικόνας</string> <string name="download_notification_channel_description">Ειδοποίηση που δείχνει την πρόοδο της λήψης αρχείων ήχου και εικόνας</string>
<string name="ytld_update_success">Νέα έκδοση εγκαταστάθηκε</string> <string name="ytld_update_success">Νέα έκδοση εγκαταστάθηκε</string>
@ -141,7 +141,7 @@
<string name="more">Περισσότερα</string> <string name="more">Περισσότερα</string>
<string name="update_app">Έλεγχος για ενημερώσεις</string> <string name="update_app">Έλεγχος για ενημερώσεις</string>
<string name="command_directory">Φάκελος Προσαρμοσμένων Εντολών</string> <string name="command_directory">Φάκελος Προσαρμοσμένων Εντολών</string>
<string name="couldnt_find_apk">Δεν ήταν δυνατή η εύρεση κατάλληλου APK.</string> <string name="couldnt_find_apk">Δεν ήταν δυνατή η εύρεση κατάλληλου APK</string>
<string name="downloading_update">Λήψη νέας έκδοσης…</string> <string name="downloading_update">Λήψη νέας έκδοσης…</string>
<string name="audio">Ήχος</string> <string name="audio">Ήχος</string>
<string name="video">Βίντεο</string> <string name="video">Βίντεο</string>

View file

@ -12,7 +12,7 @@
<string name="about">Acerca de</string> <string name="about">Acerca de</string>
<string name="source_code">Código Fuente</string> <string name="source_code">Código Fuente</string>
<string name="search_hint">Buscar o Insertar URL</string> <string name="search_hint">Buscar o Insertar URL</string>
<string name="failed_download">No se pudo descargar el archivo.</string> <string name="failed_download">No se pudo descargar el archivo</string>
<string name="download_notification_channel_name">Descargas de Archivos</string> <string name="download_notification_channel_name">Descargas de Archivos</string>
<string name="download_notification_channel_description">Notificación que muestra el progreso de las descargas de archivos de audio y video</string> <string name="download_notification_channel_description">Notificación que muestra el progreso de las descargas de archivos de audio y video</string>
<string name="you_are_in_latest_version">Estás usando la última versión</string> <string name="you_are_in_latest_version">Estás usando la última versión</string>
@ -28,7 +28,7 @@
<string name="update_app">Buscar actualizaciones</string> <string name="update_app">Buscar actualizaciones</string>
<string name="version">Versión</string> <string name="version">Versión</string>
<string name="command_directory">Directorio de Comandos Personalizados</string> <string name="command_directory">Directorio de Comandos Personalizados</string>
<string name="couldnt_find_apk">No se pudo encontrar un instalador APK correcto.</string> <string name="couldnt_find_apk">No se pudo encontrar un instalador APK correcto</string>
<string name="downloading_update">Descargando una nueva versión</string> <string name="downloading_update">Descargando una nueva versión</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -14,7 +14,7 @@
<string name="ytdl_update_hint">Utile si vous rencontrez des problèmes de téléchargement</string> <string name="ytdl_update_hint">Utile si vous rencontrez des problèmes de téléchargement</string>
<string name="source_code">Code source</string> <string name="source_code">Code source</string>
<string name="search_hint">Rechercher sur YouTube ou insérer un URL</string> <string name="search_hint">Rechercher sur YouTube ou insérer un URL</string>
<string name="failed_download">Impossible de télécharger le fichier.</string> <string name="failed_download">Impossible de télécharger le fichier</string>
<string name="download_notification_channel_name">Téléchargements de fichiers</string> <string name="download_notification_channel_name">Téléchargements de fichiers</string>
<string name="download_notification_channel_description">Notification indiquant la progression du téléchargement des fichiers audio et vidéo</string> <string name="download_notification_channel_description">Notification indiquant la progression du téléchargement des fichiers audio et vidéo</string>
<string name="you_are_in_latest_version">Utiliser la dernière version</string> <string name="you_are_in_latest_version">Utiliser la dernière version</string>
@ -32,7 +32,7 @@
<string name="update_app">Vérifier les mises à jour</string> <string name="update_app">Vérifier les mises à jour</string>
<string name="version">Version</string> <string name="version">Version</string>
<string name="command_directory">Dossier pour la commande personnalisée</string> <string name="command_directory">Dossier pour la commande personnalisée</string>
<string name="couldnt_find_apk">Impossible de trouver un APK approprié.</string> <string name="couldnt_find_apk">Impossible de trouver un APK approprié</string>
<string name="downloading_update">Téléchargement de la nouvelle version…</string> <string name="downloading_update">Téléchargement de la nouvelle version…</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Vidéo</string> <string name="video">Vidéo</string>

View file

@ -11,7 +11,7 @@
<string name="audio_format">Audio formátum</string> <string name="audio_format">Audio formátum</string>
<string name="adjust_audio">Adjust Audio</string> <string name="adjust_audio">Adjust Audio</string>
<string name="music_directory">Zene mappa</string> <string name="music_directory">Zene mappa</string>
<string name="couldnt_find_apk">Nem találhat megfelelő APK-t.</string> <string name="couldnt_find_apk">Nem találhat megfelelő APK-t</string>
<string name="ytdl_updating_started">Új verzió letöltése</string> <string name="ytdl_updating_started">Új verzió letöltése</string>
<string name="new_template">Új sablon</string> <string name="new_template">Új sablon</string>
<string name="update_ytdl_nightly">Az yt-dlp éjszakai verziója</string> <string name="update_ytdl_nightly">Az yt-dlp éjszakai verziója</string>
@ -77,7 +77,7 @@
<string name="download_notification_channel_name">Fájl letöltve</string> <string name="download_notification_channel_name">Fájl letöltve</string>
<string name="remove_results">Minden eredmény törlése</string> <string name="remove_results">Minden eredmény törlése</string>
<string name="adjust_templates">Adjust sablonok</string> <string name="adjust_templates">Adjust sablonok</string>
<string name="failed_download">Nem lehet letölteni a fájlt.</string> <string name="failed_download">Nem lehet letölteni a fájlt</string>
<string name="edit_selected">Edit kiválasztott</string> <string name="edit_selected">Edit kiválasztott</string>
<string name="sponsorblock_api_url">Sponsorblock API URL</string> <string name="sponsorblock_api_url">Sponsorblock API URL</string>
<string name="update_app">Frissítés keresése</string> <string name="update_app">Frissítés keresése</string>

View file

@ -11,7 +11,7 @@
<string name="download_all">Unduh Semua</string> <string name="download_all">Unduh Semua</string>
<string name="settings">Setelan</string> <string name="settings">Setelan</string>
<string name="search">Telusuri</string> <string name="search">Telusuri</string>
<string name="failed_download">Tidak bisa mengunduh berkas.</string> <string name="failed_download">Tidak bisa mengunduh berkas</string>
<string name="download_notification_channel_name">Unduhan Berkas</string> <string name="download_notification_channel_name">Unduhan Berkas</string>
<string name="download_notification_channel_description">Notifikasi yang memperlihatkan kemajuan pengunduhan berkas audio dan video</string> <string name="download_notification_channel_description">Notifikasi yang memperlihatkan kemajuan pengunduhan berkas audio dan video</string>
<string name="home">Beranda</string> <string name="home">Beranda</string>
@ -35,7 +35,7 @@
<string name="command_directory">Folder Perintah Kustom</string> <string name="command_directory">Folder Perintah Kustom</string>
<string name="downloading">Mengunduh</string> <string name="downloading">Mengunduh</string>
<string name="video">Video</string> <string name="video">Video</string>
<string name="couldnt_find_apk">Tidak bisa menemukan APK yang cocok.</string> <string name="couldnt_find_apk">Tidak bisa menemukan APK yang cocok</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="concurrent_fragments_summary">Jumlah fragmen sebuah video DASH/HLS asal untuk diunduh secara berbarengan</string> <string name="concurrent_fragments_summary">Jumlah fragmen sebuah video DASH/HLS asal untuk diunduh secara berbarengan</string>
<string name="limit_rate_summary">Laju unduhan maksimal (dalam satuan bita per detik), mis. 50K atau 4,2M</string> <string name="limit_rate_summary">Laju unduhan maksimal (dalam satuan bita per detik), mis. 50K atau 4,2M</string>

View file

@ -34,7 +34,7 @@
<string name="save_thumb">Salva miniatura</string> <string name="save_thumb">Salva miniatura</string>
<string name="update_ytdl">Installa nuova versione di yt-dlp</string> <string name="update_ytdl">Installa nuova versione di yt-dlp</string>
<string name="search_hint">Cerca o inserisci URL</string> <string name="search_hint">Cerca o inserisci URL</string>
<string name="failed_download">Impossibile scaricare il file.</string> <string name="failed_download">Impossibile scaricare il file</string>
<string name="download_notification_channel_description">Notifica che mostra l\'avanzamento del download di file audio e video</string> <string name="download_notification_channel_description">Notifica che mostra l\'avanzamento del download di file audio e video</string>
<string name="download_notification_channel_name">Download di file</string> <string name="download_notification_channel_name">Download di file</string>
<string name="you_are_in_latest_version">Stai utilizzando l\'ultima versione</string> <string name="you_are_in_latest_version">Stai utilizzando l\'ultima versione</string>
@ -50,7 +50,7 @@
<string name="more">Di più</string> <string name="more">Di più</string>
<string name="update_app">Controlla gli aggiornamenti</string> <string name="update_app">Controlla gli aggiornamenti</string>
<string name="command_directory">Cartella comandi personalizzata</string> <string name="command_directory">Cartella comandi personalizzata</string>
<string name="couldnt_find_apk">Impossibile trovare un APK adatto.</string> <string name="couldnt_find_apk">Impossibile trovare un APK adatto</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>
<string name="concurrent_fragments">Frammenti Concorrenti</string> <string name="concurrent_fragments">Frammenti Concorrenti</string>

View file

@ -10,7 +10,7 @@
<string name="title">כותרת</string> <string name="title">כותרת</string>
<string name="music_directory">תיקיית המוזיקה</string> <string name="music_directory">תיקיית המוזיקה</string>
<string name="warning">אזהרה</string> <string name="warning">אזהרה</string>
<string name="couldnt_find_apk">לא מצליח למצוא יישום מתאים.</string> <string name="couldnt_find_apk">לא מצליח למצוא יישום מתאים</string>
<string name="ytdl_updating_started">מוריד גירסה חדשה</string> <string name="ytdl_updating_started">מוריד גירסה חדשה</string>
<string name="concurrent_downloads_summary">מספר הורדות בו זמנית</string> <string name="concurrent_downloads_summary">מספר הורדות בו זמנית</string>
<string name="embed_subtitles">כתוביות מוטמעות</string> <string name="embed_subtitles">כתוביות מוטמעות</string>
@ -60,7 +60,7 @@
<string name="delete_files_too">מחק את הקבצים מהמכשיר</string> <string name="delete_files_too">מחק את הקבצים מהמכשיר</string>
<string name="remove_results">הסר תוצאות חיפוש</string> <string name="remove_results">הסר תוצאות חיפוש</string>
<string name="download_card_summary">הגדרות איך להוריד פריטים</string> <string name="download_card_summary">הגדרות איך להוריד פריטים</string>
<string name="failed_download">אין אפשרות להוריד את הקובץ.</string> <string name="failed_download">אין אפשרות להוריד את הקובץ</string>
<string name="edit_selected">ערוך נבחרים</string> <string name="edit_selected">ערוך נבחרים</string>
<string name="update_app">חפש עדכונים</string> <string name="update_app">חפש עדכונים</string>
<string name="search">חיפוש</string> <string name="search">חיפוש</string>

View file

@ -9,7 +9,7 @@
<string name="music_directory">音楽のフォルダ</string> <string name="music_directory">音楽のフォルダ</string>
<string name="video_directory">動画のフォルダ</string> <string name="video_directory">動画のフォルダ</string>
<string name="update_ytdl">最新の yt-dlp をインストール</string> <string name="update_ytdl">最新の yt-dlp をインストール</string>
<string name="failed_download">ファイルをダウンロードできませんでした</string> <string name="failed_download">ファイルをダウンロードできませんでした</string>
<string name="download_notification_channel_name">ファイルのダウンロード</string> <string name="download_notification_channel_name">ファイルのダウンロード</string>
<string name="you_are_in_latest_version">最新版を使用中です</string> <string name="you_are_in_latest_version">最新版を使用中です</string>
<string name="ytld_update_success">最新版をインストールしました</string> <string name="ytld_update_success">最新版をインストールしました</string>
@ -23,7 +23,7 @@
<string name="more">詳細</string> <string name="more">詳細</string>
<string name="version">バージョン</string> <string name="version">バージョン</string>
<string name="command_directory">コマンド指定用のフォルダ</string> <string name="command_directory">コマンド指定用のフォルダ</string>
<string name="couldnt_find_apk">適切な APK がありませんでした</string> <string name="couldnt_find_apk">適切な APK がありませんでした</string>
<string name="downloading_update">新しいバージョンのダウンロード</string> <string name="downloading_update">新しいバージョンのダウンロード</string>
<string name="video">動画</string> <string name="video">動画</string>
<string name="concurrent_fragments_summary">DASH/HLS ネイティブ動画の同時分割ダウンロード数</string> <string name="concurrent_fragments_summary">DASH/HLS ネイティブ動画の同時分割ダウンロード数</string>

View file

@ -13,7 +13,7 @@
<string name="dont_ask_again">Aja takon maneh</string> <string name="dont_ask_again">Aja takon maneh</string>
<string name="music_directory">Folder musik</string> <string name="music_directory">Folder musik</string>
<string name="warning">Pènget</string> <string name="warning">Pènget</string>
<string name="couldnt_find_apk">Ora bisa nemokake APK sing cocog.</string> <string name="couldnt_find_apk">Ora bisa nemokake APK sing cocog</string>
<string name="ytdl_updating_started">Download versi anyar</string> <string name="ytdl_updating_started">Download versi anyar</string>
<string name="downloads_running_try_later">Ngundhuh buruh lagi mlaku. Coba maneh mengko</string> <string name="downloads_running_try_later">Ngundhuh buruh lagi mlaku. Coba maneh mengko</string>
<string name="new_template">Cithakan anyar</string> <string name="new_template">Cithakan anyar</string>
@ -100,7 +100,7 @@
<string name="confirm_terminate">Mungkasi kabeh undhuhan lan nutup aplikasi kanthi paksa</string> <string name="confirm_terminate">Mungkasi kabeh undhuhan lan nutup aplikasi kanthi paksa</string>
<string name="errored">Kesalahan</string> <string name="errored">Kesalahan</string>
<string name="download_card_summary">Setelan carane ndownload item</string> <string name="download_card_summary">Setelan carane ndownload item</string>
<string name="failed_download">Ora bisa ngundhuh file.</string> <string name="failed_download">Ora bisa ngundhuh file</string>
<string name="cancelled">dibatalake</string> <string name="cancelled">dibatalake</string>
<string name="edit_selected">Suntingan sing dipilih</string> <string name="edit_selected">Suntingan sing dipilih</string>
<string name="log_downloads_summary">Nggawe file log kanggo saben download</string> <string name="log_downloads_summary">Nggawe file log kanggo saben download</string>

View file

@ -38,14 +38,14 @@
<string name="video_format">비디오 형식</string> <string name="video_format">비디오 형식</string>
<string name="about">개발자 정보</string> <string name="about">개발자 정보</string>
<string name="audio_format">오디오 형식</string> <string name="audio_format">오디오 형식</string>
<string name="failed_download">파일을 다운로드할 수 없습니다.</string> <string name="failed_download">파일을 다운로드할 수 없습니다</string>
<string name="download_notification_channel_name">파일 다운로드</string> <string name="download_notification_channel_name">파일 다운로드</string>
<string name="ok">확인</string> <string name="ok">확인</string>
<string name="confirm_delete_history">확인</string> <string name="confirm_delete_history">확인</string>
<string name="search_history_hint">기록에서 검색</string> <string name="search_history_hint">기록에서 검색</string>
<string name="no_results">결과 없음</string> <string name="no_results">결과 없음</string>
<string name="update_app">업데이트 확인</string> <string name="update_app">업데이트 확인</string>
<string name="couldnt_find_apk">적합한 APK를 찾을 수 없습니다.</string> <string name="couldnt_find_apk">적합한 APK를 찾을 수 없습니다</string>
<string name="audio">오디오</string> <string name="audio">오디오</string>
<string name="concurrent_fragments_summary">동시에 다운로드할 DASH/HLS 네이티브 비디오의 조각 수</string> <string name="concurrent_fragments_summary">동시에 다운로드할 DASH/HLS 네이티브 비디오의 조각 수</string>
<string name="version">버전</string> <string name="version">버전</string>

View file

@ -14,7 +14,7 @@
<string name="about">Par</string> <string name="about">Par</string>
<string name="source_code">Pirmkods</string> <string name="source_code">Pirmkods</string>
<string name="search_hint">Meklējiet vai Ievadiet URL</string> <string name="search_hint">Meklējiet vai Ievadiet URL</string>
<string name="failed_download">Nevar lejupielādēt failu.</string> <string name="failed_download">Nevar lejupielādēt failu</string>
<string name="download_notification_channel_name">Failu Lejupielādes</string> <string name="download_notification_channel_name">Failu Lejupielādes</string>
<string name="download_notification_channel_description">Paziņojums par audio un video failu lejupielādes gaitu</string> <string name="download_notification_channel_description">Paziņojums par audio un video failu lejupielādes gaitu</string>
<string name="you_are_in_latest_version">Tiek izmantota jaunākā versija</string> <string name="you_are_in_latest_version">Tiek izmantota jaunākā versija</string>
@ -32,7 +32,7 @@
<string name="update_app">Pārbaudīt atjauninājumus</string> <string name="update_app">Pārbaudīt atjauninājumus</string>
<string name="version">Versija</string> <string name="version">Versija</string>
<string name="command_directory">Pielāgotā Komandu Mape</string> <string name="command_directory">Pielāgotā Komandu Mape</string>
<string name="couldnt_find_apk">Nevarēja atrast piemērotu APK.</string> <string name="couldnt_find_apk">Nevarēja atrast piemērotu APK</string>
<string name="downloading_update">Lejupielādē jaunāko versiju…</string> <string name="downloading_update">Lejupielādē jaunāko versiju…</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -16,7 +16,7 @@
<string name="update_ytdl">Pasang versi baharu yt-dlp</string> <string name="update_ytdl">Pasang versi baharu yt-dlp</string>
<string name="source_code">Kod Sumber</string> <string name="source_code">Kod Sumber</string>
<string name="search_hint">Cari atau Masukkan URL</string> <string name="search_hint">Cari atau Masukkan URL</string>
<string name="failed_download">Tidak boleh muat turun fail.</string> <string name="failed_download">Tidak boleh muat turun fail</string>
<string name="you_are_in_latest_version">Sedang menggunakan versi terbaru</string> <string name="you_are_in_latest_version">Sedang menggunakan versi terbaru</string>
<string name="download_notification_channel_description">Notifikasi yang menunjukkan tahap muat turun bagi fail audio dan video</string> <string name="download_notification_channel_description">Notifikasi yang menunjukkan tahap muat turun bagi fail audio dan video</string>
<string name="ytld_update_success">Versi baharu telah dipasang</string> <string name="ytld_update_success">Versi baharu telah dipasang</string>
@ -31,7 +31,7 @@
<string name="more">Lagi</string> <string name="more">Lagi</string>
<string name="update_app">Semak kewujudan kemas kini</string> <string name="update_app">Semak kewujudan kemas kini</string>
<string name="version">Versi</string> <string name="version">Versi</string>
<string name="couldnt_find_apk">Tidak dapat mencari APK yang sesuai.</string> <string name="couldnt_find_apk">Tidak dapat mencari APK yang sesuai</string>
<string name="downloading_update">Memuat turun versi baharu...</string> <string name="downloading_update">Memuat turun versi baharu...</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -5,7 +5,7 @@
<string name="video_directory">Videomappe</string> <string name="video_directory">Videomappe</string>
<string name="ytdl_update_hint">Nyttig hvis du har nedlastingsproblemer</string> <string name="ytdl_update_hint">Nyttig hvis du har nedlastingsproblemer</string>
<string name="update_ytdl">Installer ny versjon av yt-dlp</string> <string name="update_ytdl">Installer ny versjon av yt-dlp</string>
<string name="failed_download">Kunne ikke laste ned filen.</string> <string name="failed_download">Kunne ikke laste ned filen</string>
<string name="download_notification_channel_name">Filnedlastinger</string> <string name="download_notification_channel_name">Filnedlastinger</string>
<string name="ytld_update_success">Ny versjon installert</string> <string name="ytld_update_success">Ny versjon installert</string>
<string name="cancel">Avbryt</string> <string name="cancel">Avbryt</string>
@ -14,7 +14,7 @@
<string name="confirm_delete_history_desc">Slett hele historikken for godt.</string> <string name="confirm_delete_history_desc">Slett hele historikken for godt.</string>
<string name="update_app">Se etter nye versjoner av programmet</string> <string name="update_app">Se etter nye versjoner av programmet</string>
<string name="command_directory">Mappe for egendefinerte kommandoer</string> <string name="command_directory">Mappe for egendefinerte kommandoer</string>
<string name="couldnt_find_apk">Fant ingen passende APK.</string> <string name="couldnt_find_apk">Fant ingen passende APK</string>
<string name="downloading_update">Laster ned ny versjon …</string> <string name="downloading_update">Laster ned ny versjon …</string>
<string name="aria2_summary">Bruk aria2c som nedlaster (istedenfor forvalget)</string> <string name="aria2_summary">Bruk aria2c som nedlaster (istedenfor forvalget)</string>
<string name="concurrent_fragments">Parallell nedlasting</string> <string name="concurrent_fragments">Parallell nedlasting</string>

View file

@ -10,7 +10,7 @@
<string name="title">Titel</string> <string name="title">Titel</string>
<string name="music_directory">Muziek Map</string> <string name="music_directory">Muziek Map</string>
<string name="warning">Waarschuwing</string> <string name="warning">Waarschuwing</string>
<string name="couldnt_find_apk">Kon geen geschikte APK vinden.</string> <string name="couldnt_find_apk">Kon geen geschikte APK vinden</string>
<string name="ytdl_updating_started">Nieuwe versie aan het downloaden</string> <string name="ytdl_updating_started">Nieuwe versie aan het downloaden</string>
<string name="command_download_notification_channel_description">Melding die de voortgang laat zien van het downloaden met een yt-dlp commando</string> <string name="command_download_notification_channel_description">Melding die de voortgang laat zien van het downloaden met een yt-dlp commando</string>
<string name="add_chapters">Hoofdstukken in Videos</string> <string name="add_chapters">Hoofdstukken in Videos</string>
@ -61,7 +61,7 @@
<string name="download_notification_channel_name">Bestand Downloads</string> <string name="download_notification_channel_name">Bestand Downloads</string>
<string name="delete_files_too">Verwijder de bestanden van het apparaat</string> <string name="delete_files_too">Verwijder de bestanden van het apparaat</string>
<string name="remove_results">Verwijder Resultaten</string> <string name="remove_results">Verwijder Resultaten</string>
<string name="failed_download">Kan bestand niet downloaden.</string> <string name="failed_download">Kan bestand niet downloaden</string>
<string name="update_app">Controleren op updates</string> <string name="update_app">Controleren op updates</string>
<string name="search">Zoeken</string> <string name="search">Zoeken</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -152,7 +152,7 @@
<string name="music_directory">Lydmappe</string> <string name="music_directory">Lydmappe</string>
<string name="updating">Oppdaterer</string> <string name="updating">Oppdaterer</string>
<string name="update_ytdl">Legg inn ei ny utgåve av yt-dlp</string> <string name="update_ytdl">Legg inn ei ny utgåve av yt-dlp</string>
<string name="failed_download">Greidde ikkje å hente fila.</string> <string name="failed_download">Greidde ikkje å hente fila</string>
<string name="ytdl_already_updating">Legg inn den nyaste utgåva</string> <string name="ytdl_already_updating">Legg inn den nyaste utgåva</string>
<string name="cancel">Avbryt</string> <string name="cancel">Avbryt</string>
<string name="ok">Greitt</string> <string name="ok">Greitt</string>
@ -160,7 +160,7 @@
<string name="command_directory">Mappe for eigne påbod</string> <string name="command_directory">Mappe for eigne påbod</string>
<string name="audio">Lyd</string> <string name="audio">Lyd</string>
<string name="video">Video</string> <string name="video">Video</string>
<string name="couldnt_find_apk">Fann ingen høvande APK.</string> <string name="couldnt_find_apk">Fann ingen høvande APK</string>
<string name="concurrent_fragments_summary">Mengd bitar av DASH/HLS-videoar å hente samstundes</string> <string name="concurrent_fragments_summary">Mengd bitar av DASH/HLS-videoar å hente samstundes</string>
<string name="downloading">Hentar</string> <string name="downloading">Hentar</string>
<string name="limit_rate_summary">Toppsnøggleiken til hentingar (i bytar i sekundet), t.d. 50K, eller 4.2M</string> <string name="limit_rate_summary">Toppsnøggleiken til hentingar (i bytar i sekundet), t.d. 50K, eller 4.2M</string>

View file

@ -33,7 +33,7 @@
<string name="exit_app">Wyjdź z aplikacji</string> <string name="exit_app">Wyjdź z aplikacji</string>
<string name="search">Szukaj</string> <string name="search">Szukaj</string>
<string name="directories">Foldery</string> <string name="directories">Foldery</string>
<string name="failed_download">Nie można pobrać pliku.</string> <string name="failed_download">Nie można pobrać pliku</string>
<string name="ytdl_update_hint">Przydatne, jeśli masz problem z pobieraniem</string> <string name="ytdl_update_hint">Przydatne, jeśli masz problem z pobieraniem</string>
<string name="download_notification_channel_description">Powiadomienie pokazujące postęp pobierania plików audio i wideo</string> <string name="download_notification_channel_description">Powiadomienie pokazujące postęp pobierania plików audio i wideo</string>
<string name="you_are_in_latest_version">Korzystasz z najnowszej wersji</string> <string name="you_are_in_latest_version">Korzystasz z najnowszej wersji</string>
@ -59,7 +59,7 @@
<string name="search_history_hint">Wyszukaj z historii przeglądania</string> <string name="search_history_hint">Wyszukaj z historii przeglądania</string>
<string name="version">Wersja</string> <string name="version">Wersja</string>
<string name="command_directory">Własny folder poleceń</string> <string name="command_directory">Własny folder poleceń</string>
<string name="couldnt_find_apk">Nie można znaleźć odpowiedniego pliku APK.</string> <string name="couldnt_find_apk">Nie można znaleźć odpowiedniego pliku APK</string>
<string name="video">Wideo</string> <string name="video">Wideo</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="concurrent_fragments">Jednoczesne fragmenty</string> <string name="concurrent_fragments">Jednoczesne fragmenty</string>

View file

@ -14,7 +14,7 @@
<string name="about">Sobre</string> <string name="about">Sobre</string>
<string name="source_code">Código fonte</string> <string name="source_code">Código fonte</string>
<string name="search_hint">Digitar um URL ou pesquisar</string> <string name="search_hint">Digitar um URL ou pesquisar</string>
<string name="failed_download">Não foi possível baixar o arquivo.</string> <string name="failed_download">Não foi possível baixar o arquivo</string>
<string name="download_notification_channel_name">Arquivos baixados</string> <string name="download_notification_channel_name">Arquivos baixados</string>
<string name="you_are_in_latest_version">Você já possui a atualização mais recente</string> <string name="you_are_in_latest_version">Você já possui a atualização mais recente</string>
<string name="ytld_update_success">Nova versão instalada</string> <string name="ytld_update_success">Nova versão instalada</string>
@ -26,7 +26,7 @@
<string name="search_history_hint">Pesquisar no histórico</string> <string name="search_history_hint">Pesquisar no histórico</string>
<string name="no_results">Nenhum resultado</string> <string name="no_results">Nenhum resultado</string>
<string name="command_directory">Pasta de comando personalizado</string> <string name="command_directory">Pasta de comando personalizado</string>
<string name="couldnt_find_apk">Não foi possível encontrar o apk adequado.</string> <string name="couldnt_find_apk">Não foi possível encontrar o apk adequado</string>
<string name="downloading_update">Baixando nova versão</string> <string name="downloading_update">Baixando nova versão</string>
<string name="audio">Áudio</string> <string name="audio">Áudio</string>
<string name="video">Vídeo</string> <string name="video">Vídeo</string>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="search_hint">Pesquisar ou inserir URL</string> <string name="search_hint">Pesquisar ou inserir URL</string>
<string name="failed_download">Não foi possível descarregar o ficheiro.</string> <string name="failed_download">Não foi possível descarregar o ficheiro</string>
<string name="ytdl_updating_started">A descarregar nova versão</string> <string name="ytdl_updating_started">A descarregar nova versão</string>
<string name="video">Vídeo</string> <string name="video">Vídeo</string>
<string name="download_notification_channel_name">Ficheiros descarregados</string> <string name="download_notification_channel_name">Ficheiros descarregados</string>
@ -55,7 +55,7 @@
<string name="sort_by">Ordem</string> <string name="sort_by">Ordem</string>
<string name="Open_File">Abrir ficheiro</string> <string name="Open_File">Abrir ficheiro</string>
<string name="download_all">Descarregar tudo</string> <string name="download_all">Descarregar tudo</string>
<string name="couldnt_find_apk">Não foi possível encontrar um APK adequado.</string> <string name="couldnt_find_apk">Não foi possível encontrar um APK adequado</string>
<string name="downloading_update">A descarregar nova versão</string> <string name="downloading_update">A descarregar nova versão</string>
<string name="audio">Áudio</string> <string name="audio">Áudio</string>
<string name="save_thumb">Guardar miniatura</string> <string name="save_thumb">Guardar miniatura</string>

View file

@ -13,7 +13,7 @@
<string name="update_ytdl">Instalează o nouă versiune de yt-dlp</string> <string name="update_ytdl">Instalează o nouă versiune de yt-dlp</string>
<string name="source_code">Codul sursă</string> <string name="source_code">Codul sursă</string>
<string name="search_hint">Caută sau Introduce adresa URL</string> <string name="search_hint">Caută sau Introduce adresa URL</string>
<string name="failed_download">Nu s-a putut descărca fișierul.</string> <string name="failed_download">Nu s-a putut descărca fișierul</string>
<string name="download_notification_channel_name">Fișiere Descărcate</string> <string name="download_notification_channel_name">Fișiere Descărcate</string>
<string name="worst_quality">Cea mai scăzută calitate</string> <string name="worst_quality">Cea mai scăzută calitate</string>
<string name="search">Căutare</string> <string name="search">Căutare</string>
@ -35,7 +35,7 @@
<string name="update_app">Verifică pentru actualizări</string> <string name="update_app">Verifică pentru actualizări</string>
<string name="version">Versiune</string> <string name="version">Versiune</string>
<string name="command_directory">Dosar de comandă personalizat</string> <string name="command_directory">Dosar de comandă personalizat</string>
<string name="couldnt_find_apk">Nu s-a putut găsi un APK potrivit.</string> <string name="couldnt_find_apk">Nu s-a putut găsi un APK potrivit</string>
<string name="downloading_update">Se descarcă versiunea nouă</string> <string name="downloading_update">Se descarcă versiunea nouă</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -8,7 +8,7 @@
<string name="source_code">Исходный код</string> <string name="source_code">Исходный код</string>
<string name="search_hint">Найдите или вставьте URL-адрес</string> <string name="search_hint">Найдите или вставьте URL-адрес</string>
<string name="update_ytdl">Установить новую версию yt-dlp</string> <string name="update_ytdl">Установить новую версию yt-dlp</string>
<string name="failed_download">Невозможно загрузить файл.</string> <string name="failed_download">Невозможно загрузить файл</string>
<string name="download_notification_channel_name">Загрузка файлов</string> <string name="download_notification_channel_name">Загрузка файлов</string>
<string name="you_are_in_latest_version">Используется последняя версия</string> <string name="you_are_in_latest_version">Используется последняя версия</string>
<string name="ytld_update_success">Установлена новая версия</string> <string name="ytld_update_success">Установлена новая версия</string>
@ -22,7 +22,7 @@
<string name="more">Больше</string> <string name="more">Больше</string>
<string name="update_app">Проверить обновления</string> <string name="update_app">Проверить обновления</string>
<string name="version">Версия</string> <string name="version">Версия</string>
<string name="couldnt_find_apk">Не удалось найти подходящий APK.</string> <string name="couldnt_find_apk">Не удалось найти подходящий APK</string>
<string name="downloading_update">Загрузка новой версии</string> <string name="downloading_update">Загрузка новой версии</string>
<string name="audio">Аудио</string> <string name="audio">Аудио</string>
<string name="video">Видео</string> <string name="video">Видео</string>

View file

@ -6,7 +6,7 @@
<string name="audio_quality">Kvalita Zvuku</string> <string name="audio_quality">Kvalita Zvuku</string>
<string name="audio_format">Formát Zvuku</string> <string name="audio_format">Formát Zvuku</string>
<string name="music_directory">Hudobný Priečinok</string> <string name="music_directory">Hudobný Priečinok</string>
<string name="couldnt_find_apk">Nepodarilo sa nájsť vhodné APK.</string> <string name="couldnt_find_apk">Nepodarilo sa nájsť vhodné APK</string>
<string name="ytdl_updating_started">Sťahuje sa nová verzia</string> <string name="ytdl_updating_started">Sťahuje sa nová verzia</string>
<string name="command_download_notification_channel_description">Oznámenie zobrazujúce priebeh sťahovania pomocou yt-dlp príkazu</string> <string name="command_download_notification_channel_description">Oznámenie zobrazujúce priebeh sťahovania pomocou yt-dlp príkazu</string>
<string name="add_chapters">Kapitoly vo Videách</string> <string name="add_chapters">Kapitoly vo Videách</string>
@ -45,7 +45,7 @@
<string name="home">Domov</string> <string name="home">Domov</string>
<string name="cancel">Zrušiť</string> <string name="cancel">Zrušiť</string>
<string name="remove_results">Vymazať Výsledky</string> <string name="remove_results">Vymazať Výsledky</string>
<string name="failed_download">Nepodarilo sa stiahnuť súbor.</string> <string name="failed_download">Nepodarilo sa stiahnuť súbor</string>
<string name="update_app">Skontrolovať aktualizácie</string> <string name="update_app">Skontrolovať aktualizácie</string>
<string name="search">Hľadať</string> <string name="search">Hľadať</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -17,7 +17,7 @@
<string name="about">Rreth</string> <string name="about">Rreth</string>
<string name="source_code">Kodi</string> <string name="source_code">Kodi</string>
<string name="search_hint">Kërko ose Vendos URL</string> <string name="search_hint">Kërko ose Vendos URL</string>
<string name="failed_download">Dështim në shkarkim.</string> <string name="failed_download">Dështim në shkarkim</string>
<string name="download_notification_channel_name">Shkarkimet e Skedarëve</string> <string name="download_notification_channel_name">Shkarkimet e Skedarëve</string>
<string name="download_notification_channel_description">Njoftimi i cili tregon progresin e shkarkimeve te skedarëve audio dhe video</string> <string name="download_notification_channel_description">Njoftimi i cili tregon progresin e shkarkimeve te skedarëve audio dhe video</string>
<string name="you_are_in_latest_version">Je ne versionin e fundit</string> <string name="you_are_in_latest_version">Je ne versionin e fundit</string>
@ -35,7 +35,7 @@
<string name="update_app">Kontrollo për përditësime</string> <string name="update_app">Kontrollo për përditësime</string>
<string name="version">Versioni</string> <string name="version">Versioni</string>
<string name="command_directory">Direktoria e Komandës</string> <string name="command_directory">Direktoria e Komandës</string>
<string name="couldnt_find_apk">Nuk u gjet një APK e vlefshme.</string> <string name="couldnt_find_apk">Nuk u gjet një APK e vlefshme</string>
<string name="downloading_update">Po shkarkohet versioni i ri</string> <string name="downloading_update">Po shkarkohet versioni i ri</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>

View file

@ -34,7 +34,7 @@
<string name="dont_ask_again">Не питај поново</string> <string name="dont_ask_again">Не питај поново</string>
<string name="music_directory">Фолдер за аудио снимке</string> <string name="music_directory">Фолдер за аудио снимке</string>
<string name="warning">Упозорење</string> <string name="warning">Упозорење</string>
<string name="couldnt_find_apk">Није могуће пронаћи одговарајући APK.</string> <string name="couldnt_find_apk">Није могуће пронаћи одговарајући APK</string>
<string name="video_recommendations_summary">Добијте препоручене YouTube видео снимке на почетном екрану с PIPED API-ја</string> <string name="video_recommendations_summary">Добијте препоручене YouTube видео снимке на почетном екрану с PIPED API-ја</string>
<string name="codec">Кодек</string> <string name="codec">Кодек</string>
<string name="select_backup_categories">Изаберите категорије резервне копије</string> <string name="select_backup_categories">Изаберите категорије резервне копије</string>
@ -228,7 +228,7 @@
<string name="errored">Неисправно</string> <string name="errored">Неисправно</string>
<string name="download_card_summary">Подешавања за преузимање предмета</string> <string name="download_card_summary">Подешавања за преузимање предмета</string>
<string name="preferred_format_id_summary">Изаберите формат са овим ID-ом на картици за преузимање</string> <string name="preferred_format_id_summary">Изаберите формат са овим ID-ом на картици за преузимање</string>
<string name="failed_download">Није могуће преузети фајл.</string> <string name="failed_download">Није могуће преузети фајл</string>
<string name="Theme">Тема</string> <string name="Theme">Тема</string>
<string name="cancelled">Отказано</string> <string name="cancelled">Отказано</string>
<string name="edit_selected">Измени изабрано</string> <string name="edit_selected">Измени изабрано</string>

View file

@ -14,7 +14,7 @@
<string name="update_ytdl">yt-dlp\'nin yeni sürümünü yükle</string> <string name="update_ytdl">yt-dlp\'nin yeni sürümünü yükle</string>
<string name="source_code">Kaynak Kodu</string> <string name="source_code">Kaynak Kodu</string>
<string name="search_hint">Ara veya URL Ekle</string> <string name="search_hint">Ara veya URL Ekle</string>
<string name="failed_download"> Dosya indirilemedi.</string> <string name="failed_download">" Dosya indirilemedi"</string>
<string name="download_notification_channel_name">Dosya İndirmeleri</string> <string name="download_notification_channel_name">Dosya İndirmeleri</string>
<string name="download_notification_channel_description">Ses ve video dosyaların indirilmesindeki ilerlemeyi gösteren bildirim</string> <string name="download_notification_channel_description">Ses ve video dosyaların indirilmesindeki ilerlemeyi gösteren bildirim</string>
<string name="you_are_in_latest_version">Son sürümü kullanıyorsun</string> <string name="you_are_in_latest_version">Son sürümü kullanıyorsun</string>
@ -32,7 +32,7 @@
<string name="update_app">Güncellemeleri kontrol et</string> <string name="update_app">Güncellemeleri kontrol et</string>
<string name="version">Sürüm</string> <string name="version">Sürüm</string>
<string name="command_directory">Özel Komut Klasörü</string> <string name="command_directory">Özel Komut Klasörü</string>
<string name="couldnt_find_apk">Uygun APK bulunamadı.</string> <string name="couldnt_find_apk">Uygun APK bulunamadı</string>
<string name="downloading_update">Yeni sürüm indiriliyor</string> <string name="downloading_update">Yeni sürüm indiriliyor</string>
ile sınırla ile sınırla
<string name="audio">Ses</string> <string name="audio">Ses</string>

View file

@ -22,7 +22,7 @@
<string name="source_code">Вихідний код</string> <string name="source_code">Вихідний код</string>
<string name="update_ytdl">Встановити нову версію yt-dlp</string> <string name="update_ytdl">Встановити нову версію yt-dlp</string>
<string name="about">Про застосунок</string> <string name="about">Про застосунок</string>
<string name="failed_download">Не вдалося завантажити файл.</string> <string name="failed_download">Не вдалося завантажити файл</string>
<string name="download_notification_channel_name">Завантаження файлів</string> <string name="download_notification_channel_name">Завантаження файлів</string>
<string name="download_notification_channel_description">Сповіщення про хід завантаження аудіо- та відеофайлів</string> <string name="download_notification_channel_description">Сповіщення про хід завантаження аудіо- та відеофайлів</string>
<string name="exit_app">Вийти зі застосунку</string> <string name="exit_app">Вийти зі застосунку</string>
@ -44,7 +44,7 @@
<string name="update_app">Перевірка наявності оновлення</string> <string name="update_app">Перевірка наявності оновлення</string>
<string name="limit_rate_summary">Максимальна швидкість завантаження (у байтах за секунду), наприклад, 50K або 4.2M</string> <string name="limit_rate_summary">Максимальна швидкість завантаження (у байтах за секунду), наприклад, 50K або 4.2M</string>
<string name="version">Версія</string> <string name="version">Версія</string>
<string name="couldnt_find_apk">Не вдалося знайти відповідний APK.</string> <string name="couldnt_find_apk">Не вдалося знайти відповідний APK</string>
<string name="limit_rate">Обмеження швидкості завантаження</string> <string name="limit_rate">Обмеження швидкості завантаження</string>
<string name="downloading">Завантаження</string> <string name="downloading">Завантаження</string>
<string name="downloading_update">Завантаження нової версії</string> <string name="downloading_update">Завантаження нової версії</string>

View file

@ -2,7 +2,7 @@
<resources> <resources>
<string name="update_ytdl">Cài đặt phiên bản mới của yt-dlp</string> <string name="update_ytdl">Cài đặt phiên bản mới của yt-dlp</string>
<string name="search">Tìm kiếm</string> <string name="search">Tìm kiếm</string>
<string name="couldnt_find_apk">Không thể tìm thấy APK phù hợp.</string> <string name="couldnt_find_apk">Không thể tìm thấy APK phù hợp</string>
<string name="remove_all">Loại bỏ tất cả</string> <string name="remove_all">Loại bỏ tất cả</string>
<string name="remove_results">Dọn dẹp Kết quả</string> <string name="remove_results">Dọn dẹp Kết quả</string>
<string name="download_all">Tải xuống tất cả</string> <string name="download_all">Tải xuống tất cả</string>
@ -14,7 +14,7 @@
<string name="ytdl_update_hint">Hữu ích nếu bạn gặp sự cố khi tải xuống</string> <string name="ytdl_update_hint">Hữu ích nếu bạn gặp sự cố khi tải xuống</string>
<string name="source_code">Mã nguồn</string> <string name="source_code">Mã nguồn</string>
<string name="search_hint">Tìm kiếm hoặc chèn URL</string> <string name="search_hint">Tìm kiếm hoặc chèn URL</string>
<string name="failed_download">Không thể tải xuống tệp.</string> <string name="failed_download">Không thể tải xuống tệp</string>
<string name="download_notification_channel_name">Tệp tải xuống</string> <string name="download_notification_channel_name">Tệp tải xuống</string>
<string name="you_are_in_latest_version">Sử dụng phiên bản mới nhất</string> <string name="you_are_in_latest_version">Sử dụng phiên bản mới nhất</string>
<string name="ytld_update_success">Phiên bản mới được cài đặt</string> <string name="ytld_update_success">Phiên bản mới được cài đặt</string>

View file

@ -6,7 +6,7 @@
<string name="home">首页</string> <string name="home">首页</string>
<string name="directories">文件夹</string> <string name="directories">文件夹</string>
<string name="music_directory">音乐文件夹</string> <string name="music_directory">音乐文件夹</string>
<string name="failed_download">无法下载文件</string> <string name="failed_download">无法下载文件</string>
<string name="download_notification_channel_name">文件下载</string> <string name="download_notification_channel_name">文件下载</string>
<string name="you_are_in_latest_version">使用最新版本</string> <string name="you_are_in_latest_version">使用最新版本</string>
<string name="ytld_update_success">已安装新版本</string> <string name="ytld_update_success">已安装新版本</string>
@ -44,7 +44,7 @@
<string name="add_chapters">添加视频章节</string> <string name="add_chapters">添加视频章节</string>
<string name="cancel">取消</string> <string name="cancel">取消</string>
<string name="confirm_delete_history_desc">永久删除全部历史记录</string> <string name="confirm_delete_history_desc">永久删除全部历史记录</string>
<string name="couldnt_find_apk">找不到合适的APK</string> <string name="couldnt_find_apk">找不到合适的APK</string>
<string name="downloading_update">正在下载新版本</string> <string name="downloading_update">正在下载新版本</string>
<string name="audio">音频</string> <string name="audio">音频</string>
<string name="embed_thumb">缩略图封面</string> <string name="embed_thumb">缩略图封面</string>

View file

@ -150,10 +150,10 @@
<string name="search">搜尋</string> <string name="search">搜尋</string>
<string name="remove_results">清除結果</string> <string name="remove_results">清除結果</string>
<string name="download_all">全部下載</string> <string name="download_all">全部下載</string>
<string name="failed_download">無法下載檔案</string> <string name="failed_download">無法下載檔案</string>
<string name="you_are_in_latest_version">使用最新版本</string> <string name="you_are_in_latest_version">使用最新版本</string>
<string name="ytld_update_success">已安裝新版本</string> <string name="ytld_update_success">已安裝新版本</string>
<string name="couldnt_find_apk">找不到適合的 APK</string> <string name="couldnt_find_apk">找不到適合的 APK</string>
<string name="update_app">檢查更新</string> <string name="update_app">檢查更新</string>
<string name="more">更多</string> <string name="more">更多</string>
<string name="version">版本</string> <string name="version">版本</string>

View file

@ -855,6 +855,14 @@
<item>hev|h265</item> <item>hev|h265</item>
</string-array> </string-array>
<string-array name="video_codec_values_ytdlp">
<item></item>
<item>av01</item>
<item>vp9</item>
<item>h264</item>
<item>h265</item>
</string-array>
<string-array name="audio_codec"> <string-array name="audio_codec">
<item>@string/defaultValue</item> <item>@string/defaultValue</item>
@ -868,6 +876,12 @@
<item>opus</item> <item>opus</item>
</string-array> </string-array>
<string-array name="audio_codec_values_ytdlp">
<item></item>
<item>aac</item>
<item>opus</item>
</string-array>
<string-array name="filename_templates"> <string-array name="filename_templates">
<item>%(uploader)s___(string): Full name of the video uploader)</item> <item>%(uploader)s___(string): Full name of the video uploader)</item>
<item>%(title)s___(string): Video title)</item> <item>%(title)s___(string): Video title)</item>
@ -1083,7 +1097,7 @@
</array> </array>
<array name="ytdlp_source"> <array name="ytdlp_source">
<item>@string/defaultValue</item> <item>@string/update_ytdl_stable</item>
<item>@string/update_ytdl_nightly</item> <item>@string/update_ytdl_nightly</item>
<item>@string/update_ytdl_master</item> <item>@string/update_ytdl_master</item>
</array> </array>
@ -1095,4 +1109,226 @@
<item>master</item> <item>master</item>
</array> </array>
<!--below is for preferred audio language, not related to app's language-->
<string-array name="language_codes">
<item>af</item> <!-- Afrikaans -->
<item>sq</item> <!-- Albanian -->
<item>am</item> <!-- Amharic -->
<item>ar</item> <!-- Arabic -->
<item>hy</item> <!-- Armenian -->
<item>az</item> <!-- Azerbaijani -->
<item>eu</item> <!-- Basque -->
<item>be</item> <!-- Belarusian -->
<item>bn</item> <!-- Bengali -->
<item>bs</item> <!-- Bosnian -->
<item>bg</item> <!-- Bulgarian -->
<item>ca</item> <!-- Catalan -->
<item>ceb</item> <!-- Cebuano -->
<item>ny</item> <!-- Chichewa -->
<item>zh</item> <!-- Chinese (Simplified) -->
<item>co</item> <!-- Corsican -->
<item>hr</item> <!-- Croatian -->
<item>cs</item> <!-- Czech -->
<item>da</item> <!-- Danish -->
<item>nl</item> <!-- Dutch -->
<item>en</item> <!-- English -->
<item>eo</item> <!-- Esperanto -->
<item>et</item> <!-- Estonian -->
<item>tl</item> <!-- Filipino -->
<item>fi</item> <!-- Finnish -->
<item>fr</item> <!-- French -->
<item>fy</item> <!-- Frisian -->
<item>gl</item> <!-- Galician -->
<item>ka</item> <!-- Georgian -->
<item>de</item> <!-- German -->
<item>el</item> <!-- Greek -->
<item>gu</item> <!-- Gujarati -->
<item>ht</item> <!-- Haitian Creole -->
<item>ha</item> <!-- Hausa -->
<item>haw</item> <!-- Hawaiian -->
<item>iw</item> <!-- Hebrew -->
<item>he</item> <!-- Hebrew (legacy) -->
<item>hi</item> <!-- Hindi -->
<item>hmn</item> <!-- Hmong -->
<item>hu</item> <!-- Hungarian -->
<item>is</item> <!-- Icelandic -->
<item>ig</item> <!-- Igbo -->
<item>id</item> <!-- Indonesian -->
<item>ga</item> <!-- Irish -->
<item>it</item> <!-- Italian -->
<item>ja</item> <!-- Japanese -->
<item>jw</item> <!-- Javanese -->
<item>kn</item> <!-- Kannada -->
<item>kk</item> <!-- Kazakh -->
<item>km</item> <!-- Khmer -->
<item>rw</item> <!-- Kinyarwanda -->
<item>ko</item> <!-- Korean -->
<item>ku</item> <!-- Kurdish (Kurmanji) -->
<item>ky</item> <!-- Kyrgyz -->
<item>lo</item> <!-- Lao -->
<item>la</item> <!-- Latin -->
<item>lv</item> <!-- Latvian -->
<item>lt</item> <!-- Lithuanian -->
<item>lb</item> <!-- Luxembourgish -->
<item>mk</item> <!-- Macedonian -->
<item>mg</item> <!-- Malagasy -->
<item>ms</item> <!-- Malay -->
<item>ml</item> <!-- Malayalam -->
<item>mt</item> <!-- Maltese -->
<item>mi</item> <!-- Maori -->
<item>mr</item> <!-- Marathi -->
<item>mn</item> <!-- Mongolian -->
<item>my</item> <!-- Burmese -->
<item>ne</item> <!-- Nepali -->
<item>no</item> <!-- Norwegian -->
<item>or</item> <!-- Oriya -->
<item>ps</item> <!-- Pashto -->
<item>fa</item> <!-- Persian -->
<item>pl</item> <!-- Polish -->
<item>pt</item> <!-- Portuguese -->
<item>pa</item> <!-- Punjabi -->
<item>ro</item> <!-- Romanian -->
<item>ru</item> <!-- Russian -->
<item>sm</item> <!-- Samoan -->
<item>gd</item> <!-- Scots Gaelic -->
<item>sr</item> <!-- Serbian -->
<item>st</item> <!-- Sesotho -->
<item>sn</item> <!-- Shona -->
<item>sd</item> <!-- Sindhi -->
<item>si</item> <!-- Sinhalese -->
<item>sk</item> <!-- Slovak -->
<item>sl</item> <!-- Slovenian -->
<item>so</item> <!-- Somali -->
<item>es</item> <!-- Spanish -->
<item>su</item> <!-- Sundanese -->
<item>sw</item> <!-- Swahili -->
<item>sv</item> <!-- Swedish -->
<item>tg</item> <!-- Tajik -->
<item>ta</item> <!-- Tamil -->
<item>te</item> <!-- Telugu -->
<item>th</item> <!-- Thai -->
<item>tr</item> <!-- Turkish -->
<item>uk</item> <!-- Ukrainian -->
<item>ur</item> <!-- Urdu -->
<item>ug</item> <!-- Uyghur -->
<item>uz</item> <!-- Uzbek -->
<item>vi</item> <!-- Vietnamese -->
<item>cy</item> <!-- Welsh -->
<item>xh</item> <!-- Xhosa -->
<item>yi</item> <!-- Yiddish -->
<item>yo</item> <!-- Yoruba -->
<item>zu</item> <!-- Zulu -->
</string-array>
<string-array name="language_names">
<item>Afrikaans</item>
<item>Albanian</item>
<item>Amharic</item>
<item>Arabic</item>
<item>Armenian</item>
<item>Azerbaijani</item>
<item>Basque</item>
<item>Belarusian</item>
<item>Bengali</item>
<item>Bosnian</item>
<item>Bulgarian</item>
<item>Catalan</item>
<item>Cebuano</item>
<item>Chichewa</item>
<item>Chinese (Simplified)</item>
<item>Corsican</item>
<item>Croatian</item>
<item>Czech</item>
<item>Danish</item>
<item>Dutch</item>
<item>English</item>
<item>Esperanto</item>
<item>Estonian</item>
<item>Filipino</item>
<item>Finnish</item>
<item>French</item>
<item>Frisian</item>
<item>Galician</item>
<item>Georgian</item>
<item>German</item>
<item>Greek</item>
<item>Gujarati</item>
<item>Haitian Creole</item>
<item>Hausa</item>
<item>Hawaiian</item>
<item>Hebrew</item>
<item>Hebrew (legacy)</item>
<item>Hindi</item>
<item>Hmong</item>
<item>Hungarian</item>
<item>Icelandic</item>
<item>Igbo</item>
<item>Indonesian</item>
<item>Irish</item>
<item>Italian</item>
<item>Japanese</item>
<item>Javanese</item>
<item>Kannada</item>
<item>Kazakh</item>
<item>Khmer</item>
<item>Kinyarwanda</item>
<item>Korean</item>
<item>Kurdish (Kurmanji)</item>
<item>Kyrgyz</item>
<item>Lao</item>
<item>Latin</item>
<item>Latvian</item>
<item>Lithuanian</item>
<item>Luxembourgish</item>
<item>Macedonian</item>
<item>Malagasy</item>
<item>Malay</item>
<item>Malayalam</item>
<item>Maltese</item>
<item>Maori</item>
<item>Marathi</item>
<item>Mongolian</item>
<item>Burmese</item>
<item>Nepali</item>
<item>Norwegian</item>
<item>Oriya</item>
<item>Pashto</item>
<item>Persian</item>
<item>Polish</item>
<item>Portuguese</item>
<item>Punjabi</item>
<item>Romanian</item>
<item>Russian</item>
<item>Samoan</item>
<item>Scots Gaelic</item>
<item>Serbian</item>
<item>Sesotho</item>
<item>Shona</item>
<item>Sindhi</item>
<item>Sinhalese</item>
<item>Slovak</item>
<item>Slovenian</item>
<item>Somali</item>
<item>Spanish</item>
<item>Sundanese</item>
<item>Swahili</item>
<item>Swedish</item>
<item>Tajik</item>
<item>Tamil</item>
<item>Telugu</item>
<item>Thai</item>
<item>Turkish</item>
<item>Ukrainian</item>
<item>Urdu</item>
<item>Uyghur</item>
<item>Uzbek</item>
<item>Vietnamese</item>
<item>Welsh</item>
<item>Xhosa</item>
<item>Yiddish</item>
<item>Yoruba</item>
<item>Zulu</item>
</string-array>
</resources> </resources>

View file

@ -17,7 +17,7 @@
<string name="about">About</string> <string name="about">About</string>
<string name="source_code">Source Code</string> <string name="source_code">Source Code</string>
<string name="search_hint">Search or Insert URL</string> <string name="search_hint">Search or Insert URL</string>
<string name="failed_download">Could not download file.</string> <string name="failed_download">Could not download file</string>
<string name="download_notification_channel_name">File Downloads</string> <string name="download_notification_channel_name">File Downloads</string>
<string name="download_notification_channel_description">Notification showing the progress of downloading audio and video files</string> <string name="download_notification_channel_description">Notification showing the progress of downloading audio and video files</string>
<string name="you_are_in_latest_version">Using the latest version</string> <string name="you_are_in_latest_version">Using the latest version</string>
@ -36,7 +36,7 @@
<string name="update_app">Check for updates</string> <string name="update_app">Check for updates</string>
<string name="version">Version</string> <string name="version">Version</string>
<string name="command_directory">Custom Command Folder</string> <string name="command_directory">Custom Command Folder</string>
<string name="couldnt_find_apk">Could not find a suitable APK.</string> <string name="couldnt_find_apk">Could not find a suitable APK</string>
<string name="downloading_update">Downloading new version</string> <string name="downloading_update">Downloading new version</string>
<string name="audio">Audio</string> <string name="audio">Audio</string>
<string name="video">Video</string> <string name="video">Video</string>
@ -323,6 +323,8 @@
<string name="export_file">Export File</string> <string name="export_file">Export File</string>
<string name="ytdl_source">yt-dlp Source</string> <string name="ytdl_source">yt-dlp Source</string>
<string name="update_ytdl_master">Master Version of yt-dlp</string> <string name="update_ytdl_master">Master Version of yt-dlp</string>
<string name="update_ytdl_stable">Stable Version of yt-dlp</string>
<string name="buffer_size">Buffer Size</string> <string name="buffer_size">Buffer Size</string>
<string name="buffer_size_summary">Size of download buffer, e.g. 1024 or 16K (default is 1024)</string> <string name="buffer_size_summary">Size of download buffer, e.g. 1024 or 16K (default is 1024)</string>
<string name="preferred_audio_language">Preferred Audio Language</string>
</resources> </resources>

View file

@ -153,6 +153,7 @@
android:entries="@array/video_codec" android:entries="@array/video_codec"
android:entryValues="@array/video_codec_values" android:entryValues="@array/video_codec_values"
android:icon="@drawable/ic_code" android:icon="@drawable/ic_code"
app:useSimpleSummaryProvider="true"
app:key="video_codec" app:key="video_codec"
app:title="@string/preferred_video_codec" /> app:title="@string/preferred_video_codec" />
@ -161,9 +162,19 @@
android:entries="@array/audio_codec" android:entries="@array/audio_codec"
android:entryValues="@array/audio_codec_values" android:entryValues="@array/audio_codec_values"
android:icon="@drawable/ic_code" android:icon="@drawable/ic_code"
app:useSimpleSummaryProvider="true"
app:key="audio_codec" app:key="audio_codec"
app:title="@string/preferred_audio_codec" /> app:title="@string/preferred_audio_codec" />
<ListPreference
app:icon="@drawable/ic_language"
app:dialogTitle="@string/preferred_audio_language"
app:entries="@array/language_names"
app:entryValues="@array/language_codes"
app:key="audio_language"
app:useSimpleSummaryProvider="true"
app:title="@string/preferred_audio_language" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch" android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="false" app:defaultValue="false"

View file

@ -57,7 +57,7 @@
app:useSimpleSummaryProvider="true" app:useSimpleSummaryProvider="true"
app:title="@string/format_order" /> app:title="@string/format_order" />
<EditTextPreference <Preference
app:key="piped_instance" app:key="piped_instance"
app:defaultValue="" app:defaultValue=""
android:summary="@string/piped_instance_summary" android:summary="@string/piped_instance_summary"

View file

@ -15,6 +15,7 @@ buildscript {
// supports java 1.6 // supports java 1.6
commonsCompressVer = '1.12' commonsCompressVer = '1.12'
youtubedlAndroidVer = "-SNAPSHOT" youtubedlAndroidVer = "-SNAPSHOT"
youtubedlAndroidVerNoPyCrypto = "97bee6c0e8"
workVer = "2.8.1" workVer = "2.8.1"
composeVer = '1.4.2' composeVer = '1.4.2'
kotlinVer = "1.7.21" kotlinVer = "1.7.21"