From c05224336a78bb28dcdd667230c23178df7b8650 Mon Sep 17 00:00:00 2001
From: deniscerri <64997243+deniscerri@users.noreply.github.com>
Date: Wed, 27 Sep 2023 19:13:56 +0200
Subject: [PATCH] remove trim filenames command from command type fixed app not
showing formats when it has generic formats fixed author getting written as
NA for kick videos added separate channel for the worker notification that
users can turn off
---
README-sq.md | 133 +++++++++++
README.MD | 2 +
app/build.gradle | 3 +
app/src/main/AndroidManifest.xml | 2 +-
.../com/deniscerri/ytdlnis/MainActivity.kt | 6 +
.../database/viewmodel/DownloadViewModel.kt | 35 +--
.../com/deniscerri/ytdlnis/ui/BaseActivity.kt | 5 -
.../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 11 +-
.../downloadcard/CutVideoBottomSheetDialog.kt | 3 +-
.../ui/downloadcard/DownloadAudioFragment.kt | 15 +-
.../downloadcard/DownloadCommandFragment.kt | 2 -
.../DownloadMultipleBottomSheetDialog.kt | 7 +-
.../ui/downloadcard/DownloadVideoFragment.kt | 23 +-
.../FormatSelectionBottomSheetDialog.kt | 2 +-
.../more/settings/GeneralSettingsFragment.kt | 44 +---
.../com/deniscerri/ytdlnis/util/InfoUtil.kt | 210 ++++++++++--------
.../ytdlnis/util/NotificationUtil.kt | 18 +-
.../com/deniscerri/ytdlnis/util/UpdateUtil.kt | 11 +-
.../deniscerri/ytdlnis/work/DownloadWorker.kt | 14 +-
app/src/main/res/values/arrays.xml | 19 +-
app/src/main/res/values/strings.xml | 2 +-
app/src/main/res/xml/general_preferences.xml | 7 -
.../main/res/xml/processing_preferences.xml | 2 +-
23 files changed, 361 insertions(+), 215 deletions(-)
create mode 100644 README-sq.md
diff --git a/README-sq.md b/README-sq.md
new file mode 100644
index 00000000..a680986a
--- /dev/null
+++ b/README-sq.md
@@ -0,0 +1,133 @@
+
+
+ YTDLnis
+
+
+
+
+
+ YTDLnis është një shkarkues video/audio falas dhe me burim të hapur duke përdorur yt-dlp për Android 6.0 dhe më lart.
+
+
+
+
+[](https://github.com/deniscerri/ytdlnis/releases/latest)
+[](https://android.izzysoft.de/repo/apk/com.deniscerri.ytdl)
+[](https://ytdlnis.en.uptodown.com/android/download)
+
+
+[](https://github.com/deniscerri/ytdlnis/releases)
+[](https://github.com/deniscerri/ytdlnis/releases)
+[](https://hosted.weblate.org/engage/ytdlnis/?utm_source=widget)
+[](https://discord.gg/WW3KYWxAPm)
+[](https://t.me/ytdlnis)
+[](https://t.me/ytdlnisupdates)
+
+
+
+
+
+
+
+## 💡 Veçoritë:
+
+- shkarko skedarë audio/video nga më shumë se 1000 website
+- përpunoni lista
+- modifikoni çdo artikull të listës veç e veç si me një artikull normal shkarkimi.
+- zgjidhni një format të përbashkët për të gjithë artikujt dhe/ose zgjidhni formate të shumta audio në rast se po i shkarkoni si video
+- zgjidhni një lloj shkarkimi për të gjithë artikujt
+- zgjidhni një shabllon të emrit të skedarit për të gjithë artikujt
+- përditëso llojin i shkarkimit në audio/video/komandë pme një klik
+- vendosni shkarkimet në radhë dhe planifikoni ato sipas datës dhe orës
+- gjithashtu mund të planifikoni shumë artikuj në të njëjtën kohë
+- shkarkoni shumë artikuj në të njëjtën kohë
+- përdorni komanda dhe shabllone të personalizuara ose shkoni në modalitetin e plotë yt-dlp me një terminal të integruar
+- mund të ruani dhe riktheni shabllonet, në mënyrë që të mund t'i ndani me miqtë tuaj
+- Mbështetje për BISKOTAT. Hyni me llogaritë tuaja dhe shkarkoni video private/të padisponueshme, zhbllokoni formatet premium etj.
+- prit video bazuar sipas kohës dhe kapitujt e videos (Kjo veçori yt-dlp është eksperimentale në projektin origjinal)
+- ju mund të bëni prerje të pafundme
+- hiqni elementet e SPONSORBLOCK (si pjeset pa muzike) nga artikulli
+- futini ato si kapituj në videon tuaj
+- fut titrat/metadatat/kapitujt etj
+- modifikoni titullin dhe autorin
+- ndani artikullin në skedarë të veçantë në varësi të kapitujve të tij
+- zgjidhni formate të ndryshme shkarkimi
+- shfaq karte direkt nga menyja e shpërndarjes, nuk ka nevojë të hapni aplikacionin
+- mund të krijoni një skedar txt dhe ta plotësoni me linke/playliste/fjale kerkimi të ndara nga një rresht i ri dhe aplikacioni do t'i përpunojë ato
+- kërkoni ose futni një link nga aplikacioni
+- mund të grumbulloni kërkime në mënyrë që t'i përpunoni ato në të njëjtën kohë
+- regjistrimet e shkarkimeve në rast problemesh
+- rishkarkimi i shkarkimeve të anuluara ose të dështuara
+- mund të përdorni gjeste për të rrëshqitur majtas për ta shkarkuar përsëri dhe djathtas për t'i fshirë
+- mund të klikoni gjatë butonin e rishkarkimit në fletën e detajeve për të shfaqur kartën e shkarkimit për më shumë funksionalitet
+- INCOGNITO kur nuk dëshironi të ruani një histori shkarkimi ose regjistra
+- mënyra e shkarkimit të shpejtë
+- shkarkoni menjëherë pa pasur nevojë të prisni që të dhënat të përpunohen. Fikni kartën e poshtme dhe ajo do të fillojë menjëherë
+- hapni / ndani skedarët e shkarkuar menjëherë nga njoftimi i përfunduar
+- shumica e veçorive yt-dlp janë zbatuar, sugjerimet janë të mirëseardhura
+- ndërfaqja e MATERIAL U
+- opsionet ngjyrash
+- rezervoni dhe rivendosni veçoritë e aplikacionit. (Pothuajse gjithçka mund të rezervohet dhe mund te shperndash me shoke)
+- Arkitektura MVVM me WorkManager
+
+## 📲 Fotot
+
+
+

+

+

+

+

+

+

+

+

+

+

+

+

+
+
+## 💬 Kontakt
+
+Bashkohuni me [Kanalin tonë Telegram](https://t.me/ytdlnis) ose [Diskord](https://discord.gg/WW3KYWxAPm) për diskutim, njoftime dhe publikime!
+
+## 🔑 Lidhu me ReVanced
+
+Emri i paketës së aplikacionit është "com.deniscerri.ytdl"
+
+## 📝 Ndihmo për të përkthyer në Weblate
+
+
+
+
+
+
+
+
+
+## 😇 Kontributo
+
+Nëse dëshironi të kontribuoni. Ju lutemi lexoni seksionin [Kontribimi](CONTRIBUTING.MD).
+
+## 📄 Liçensa
+
+[GNU GPL v3.0](https://github.com/deniscerri/ytdlnis/blob/main/LICENSE)
+
+⚠️ Paralajmërim
+
+Përveç kodit burimor të licencuar sipas licencës GPLv3, të gjitha palët e tjera janë të ndaluara të përdorin emrin 'YTDLnis' si një aplikacion shkarkues dhe e njëjta gjë vlen edhe për derivatet e tij. Derivatet përfshijnë por nuk kufizohen në forks dhe ndërtime jozyrtare.
+
+## 🙏 Falenderimet
+
+- [yt-dlp](https://github.com/yt-dlp/yt-dlp) dhe kontribuesit e tij për të bërë të mundur këtë mjet. Pa të ky aplikacion nuk do të ekzistonte.
+- [youtubedl-android](https://github.com/yausername/youtubedl-android) për transferimin e yt-dlp në android.
+- [dvd](https://github.com/yausername/dvd) për të treguar se si të zbatohet youtubedl-android
+- [seal](https://github.com/JunkFood02/Seal) për elementë dhe veçori të caktuara të dizajnit doja të përdorja gjithashtu në këtë aplikacion
+- [decipher3114](https://github.com/decipher3114) për ikonën e aplikacionit
+
+dhe shumë të huaj të tjerë nga interneti.
diff --git a/README.MD b/README.MD
index 2beee643..5b42c327 100644
--- a/README.MD
+++ b/README.MD
@@ -6,6 +6,8 @@
English
|
+
Shqip
+ |
Azərbaycanca
|
Português
diff --git a/app/build.gradle b/app/build.gradle
index f7029470..f9888e51 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -76,6 +76,9 @@ android {
}
}
+ lintOptions{
+ disable 'MissingTranslation'
+ }
android.applicationVariants.configureEach { variant ->
variant.outputs.each { output ->
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7ea3e030..a4b577a0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -84,7 +84,7 @@
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt
index 126d0756..35d934ab 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt
@@ -198,6 +198,12 @@ class MainActivity : BaseActivity() {
}
true
}
+ //settings button
+ (navigationView as NavigationView).menu.getItem(8).setOnMenuItemClickListener {
+ val intent = Intent(context, SettingsActivity::class.java)
+ startActivity(intent)
+ true
+ }
(navigationView as NavigationView).getHeaderView(0).findViewById(R.id.title).text = ThemeUtil.getStyledAppName(this)
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt
index 658f9871..e82b5f2a 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt
@@ -122,14 +122,14 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
audioFormatIDPreference = sharedPreferences.getString("format_id_audio", "").toString().split(",").filter { it.isNotEmpty() }
val confTmp = Configuration(application.resources.configuration)
- confTmp.locale = Locale(sharedPreferences.getString("app_language", "en")!!)
+ confTmp.setLocale(Locale(sharedPreferences.getString("app_language", "en")!!))
val metrics = DisplayMetrics()
resources = Resources(application.assets, metrics, confTmp)
videoContainer = sharedPreferences.getString("video_format", "Default")
- defaultVideoFormats = getGenericVideoFormats()
- bestVideoFormat = defaultVideoFormats.last()
+ defaultVideoFormats = infoUtil.getGenericVideoFormats(resources)
+ bestVideoFormat = defaultVideoFormats.first()
audioContainer = sharedPreferences.getString("audio_format", "mp3")
bestAudioFormat = if (audioFormatIDPreference.isEmpty()){
@@ -387,10 +387,10 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
return cloneFormat (
try {
try{
- formats.filter { it.format_note.contains("audio", ignoreCase = true)}.sortedBy { it.format_id }
+ formats.filter { it.format_note.contains("audio", ignoreCase = true)}
.firstOrNull { audioFormatIDPreference.indexOfFirst { a -> a.contains(it.format_id) } >= 0 || it.container == audioContainer} ?: throw Exception()
}catch (e: Exception){
- formats.last { it.format_note.contains("audio", ignoreCase = true) }
+ formats.first { it.format_note.contains("audio", ignoreCase = true) }
}
}catch (e: Exception){
bestAudioFormat
@@ -401,18 +401,17 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
Type.video -> {
return cloneFormat(
try {
- val theFormats = formats.filter { !it.format_note.contains("audio", true) }.sortedBy { it.format_id }.ifEmpty { defaultVideoFormats }.sortedByDescending { it.filesize }
+ val theFormats = formats.filter { !it.format_note.contains("audio", true) }.ifEmpty { defaultVideoFormats.sortedByDescending { it.filesize } }
when (videoQualityPreference) {
"worst" -> {
- theFormats.first()
+ theFormats.last()
}
else /*best*/ -> {
val requirements: MutableList<(Format) -> Boolean> = mutableListOf()
requirements.add { it: Format -> formatIDPreference.sorted().contains(it.format_id) }
requirements.add { it: Format -> if (videoContainer == "mp4") it.container.equals("mpeg_4", true) else it.container.equals(videoContainer, true)}
- requirements.add { it: Format -> it.format_note.contains(videoQualityPreference.substring(0, videoQualityPreference.length - 1)) }
- requirements.add { it: Format -> it.vcodec.startsWith(videoCodec!!, true) }
-
+ requirements.add { it: Format -> it.format_note.contains(videoQualityPreference.split("_")[0].dropLast(1)) }
+ requirements.add { it: Format -> "^(${videoCodec}).+$".toRegex(RegexOption.IGNORE_CASE).matches(it.vcodec)}
theFormats.maxByOrNull { f -> requirements.count{ req -> req(f)} } ?: throw Exception()
}
}
@@ -440,23 +439,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
)
}
- fun getGenericAudioFormats() : MutableList{
- val audioFormats = resources.getStringArray(R.array.audio_formats)
- val formats = mutableListOf()
- val containerPreference = sharedPreferences.getString("audio_format", "")
- audioFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
- audioFormatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"","", "",1, it)) }
- return formats
- }
- fun getGenericVideoFormats() : MutableList{
- val videoFormats = resources.getStringArray(R.array.video_formats_values)
- val formats = mutableListOf()
- val containerPreference = sharedPreferences.getString("video_format", "")
- videoFormats.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",0, it.split("_")[0])) }
- formatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",1, it)) }
- return formats
- }
fun getLatestCommandTemplateAsFormat() : Format {
val t = commandTemplateDao.getFirst()
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/BaseActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/BaseActivity.kt
index 52b2c011..1b46367a 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/BaseActivity.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/BaseActivity.kt
@@ -2,11 +2,6 @@ package com.deniscerri.ytdlnis.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.ViewCompat
-import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsCompat
-import androidx.core.view.updatePadding
-import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.util.ThemeUtil
import com.google.android.material.elevation.SurfaceColors
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt
index c52b11cf..1c9483ea 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt
@@ -435,7 +435,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
}
@SuppressLint("InflateParams")
- private suspend fun updateSearchViewItems(it: Editable?, linkYouCopied: View?){
+ private suspend fun updateSearchViewItems(searchQuery: Editable?, linkYouCopied: View?){
searchSuggestionsLinearLayout!!.visibility = GONE
searchHistoryLinearLayout!!.visibility = GONE
searchSuggestionsLinearLayout!!.removeAllViews()
@@ -449,16 +449,15 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
searchView!!.editText.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_plus, 0)
}
val suggestions = withContext(Dispatchers.IO){
- if (it!!.isEmpty()) {
- resultViewModel.getSearchHistory().map { it.query }
- }else if (sharedPreferences!!.getBoolean("search_suggestions", false)){
- infoUtil!!.getSearchSuggestions(it.toString())
+ resultViewModel.getSearchHistory().map { it.query }.filter { it.contains(searchQuery!!) } +
+ if (sharedPreferences!!.getBoolean("search_suggestions", false)){
+ infoUtil!!.getSearchSuggestions(searchQuery.toString())
}else{
emptyList()
}
}
- if (it!!.isEmpty()){
+ if (searchQuery!!.isEmpty()){
for (i in suggestions.indices) {
val v = LayoutInflater.from(fragmentContext)
.inflate(R.layout.search_suggestion_item, null)
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/CutVideoBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/CutVideoBottomSheetDialog.kt
index f3345bfa..8b18d986 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/CutVideoBottomSheetDialog.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/CutVideoBottomSheetDialog.kt
@@ -335,7 +335,6 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
if ((event!!.action == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
- val values = rangeSlider.values
var endTimestamp = (rangeSlider.valueTo.toInt() * timeSeconds) / 100
toTextInput.editText!!.clearFocus()
@@ -361,7 +360,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
rangeSlider.setValues(startValue, endValue)
okBtn.isEnabled = startValue != 0F || endValue != 100F
try {
- player.seekTo(startSeconds.toLong() * 1000)
+ player.seekTo((seconds.toLong() - 4L) * 1000)
player.play()
}catch (ignored: Exception) {}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
index fa176495..e8a8755d 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadAudioFragment.kt
@@ -38,7 +38,6 @@ import java.io.File
class DownloadAudioFragment(private var resultItem: ResultItem, private var currentDownloadItem: DownloadItem?) : Fragment(), TitleAuthorSync {
- private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
@@ -46,6 +45,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
private lateinit var saveDir : TextInputLayout
private lateinit var freeSpace : TextView
private lateinit var infoUtil: InfoUtil
+ private lateinit var genericAudioFormats: MutableList
lateinit var downloadItem : DownloadItem
lateinit var title : TextInputLayout
@@ -55,12 +55,12 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- _binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_audio, container, false)
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
infoUtil = InfoUtil(requireContext())
+ genericAudioFormats = infoUtil.getGenericAudioFormats(requireContext().resources)
return fragmentView
}
@@ -129,7 +129,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
downloadItem.allFormats.filter { it.format_note.contains("audio", ignoreCase = true) }
.maxByOrNull { it.filesize }!!
}.onFailure {
- downloadItem.format = downloadViewModel.getGenericAudioFormats().last()
+ downloadItem.format = genericAudioFormats.last()
}
}
}
@@ -142,7 +142,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
val containerAutoCompleteTextView =
view.findViewById(R.id.container_textview)
- if (formats.isEmpty()) formats = downloadViewModel.getGenericAudioFormats()
+ if (formats.isEmpty()) formats = genericAudioFormats
val formatCard = view.findViewById(R.id.format_card_constraintLayout)
val chosenFormat = downloadItem.format
@@ -154,16 +154,17 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
lifecycleScope.launch {
withContext(Dispatchers.IO){
resultItem.formats.removeAll(formats.toSet())
- resultItem.formats.addAll(allFormats.first())
+ resultItem.formats.addAll(allFormats.first().filter { !genericAudioFormats.contains(it) })
resultViewModel.update(resultItem)
}
}
- formats = allFormats.first().toMutableList()
+ formats = allFormats.first().filter { !genericAudioFormats.contains(it) }.toMutableList()
+ formats.removeAll(genericAudioFormats)
}
}
formatCard.setOnClickListener{
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
- val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats), listener)
+ val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats.ifEmpty { genericAudioFormats }), listener)
bottomSheet.show(parentFragmentManager, "formatSheet")
}
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
index 94058679..13f77d6b 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt
@@ -42,7 +42,6 @@ import kotlinx.coroutines.withContext
import java.io.File
class DownloadCommandFragment(private val resultItem: ResultItem, private var currentDownloadItem: DownloadItem?) : Fragment() {
- private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
@@ -57,7 +56,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- _binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_command, container, false)
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt
index 1a948230..0c0b9b42 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt
@@ -50,6 +50,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.receiver.ShareActivity
import com.deniscerri.ytdlnis.util.FileUtil
+import com.deniscerri.ytdlnis.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil
import com.deniscerri.ytdlnis.util.UiUtil.enableFastScroll
import com.deniscerri.ytdlnis.work.UpdatePlaylistFormatsWorker
@@ -78,6 +79,7 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList
private lateinit var bottomAppBar: BottomAppBar
private lateinit var filesize : TextView
@@ -90,6 +92,7 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList listOf>(downloadViewModel.getGenericAudioFormats())
- else -> listOf>(downloadViewModel.getGenericVideoFormats())
+ DownloadViewModel.Type.audio -> listOf>(infoUtil.getGenericAudioFormats(requireContext().resources))
+ else -> listOf>(infoUtil.getGenericVideoFormats(requireContext().resources))
}
}
val bottomSheet = FormatSelectionBottomSheetDialog(items, formats, formatListener)
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
index 1be349d0..d0119119 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadVideoFragment.kt
@@ -25,7 +25,6 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
-import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil
import com.deniscerri.ytdlnis.util.UiUtil
@@ -39,7 +38,6 @@ import java.io.File
class DownloadVideoFragment(private val resultItem: ResultItem, private var currentDownloadItem: DownloadItem?) : Fragment(), TitleAuthorSync {
- private var _binding : FragmentHomeBinding? = null
private var fragmentView: View? = null
private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel
@@ -50,6 +48,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
private lateinit var saveDir : TextInputLayout
private lateinit var freeSpace : TextView
private lateinit var infoUtil: InfoUtil
+ private lateinit var genericVideoFormats: MutableList
lateinit var downloadItem: DownloadItem
@@ -58,12 +57,12 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- _binding = FragmentHomeBinding.inflate(inflater, container, false)
fragmentView = inflater.inflate(R.layout.fragment_download_video, container, false)
activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this@DownloadVideoFragment)[ResultViewModel::class.java]
infoUtil = InfoUtil(requireContext())
+ genericVideoFormats = infoUtil.getGenericVideoFormats(requireContext().resources)
return fragmentView
}
@@ -136,7 +135,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
downloadItem.allFormats.filter { it.vcodec.isNotEmpty() }
.maxByOrNull { it.filesize }!!
}.onFailure {
- downloadItem.format = downloadViewModel.getGenericVideoFormats().last()
+ downloadItem.format = genericVideoFormats.last()
}
}
}
@@ -149,7 +148,7 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
var containerPreference = sharedPreferences.getString("video_format", "Default")
if (containerPreference == "Default") containerPreference = getString(R.string.defaultValue)
- if (formats.isEmpty()) formats = downloadViewModel.getGenericVideoFormats()
+ if (formats.isEmpty()) formats = genericVideoFormats
val formatCard = view.findViewById(R.id.format_card_constraintLayout)
@@ -158,22 +157,24 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
val listener = object : OnFormatClickListener {
override fun onFormatClick(allFormats: List>, item: List) {
downloadItem.format = item.first().format
- item.first().audioFormats?.map { it.format_id }
- ?.let { downloadItem.videoPreferences.audioFormatIDs.addAll(it) }
+ item.first().audioFormats?.map { it.format_id }?.let {
+ downloadItem.videoPreferences.audioFormatIDs.clear()
+ downloadItem.videoPreferences.audioFormatIDs.addAll(it)
+ }
lifecycleScope.launch {
withContext(Dispatchers.IO){
- resultItem.formats.removeAll(formats.toSet())
- resultItem.formats.addAll(allFormats.first())
+ resultItem.formats.removeAll(formats)
+ resultItem.formats.addAll(allFormats.first().filter { !genericVideoFormats.contains(it) })
resultViewModel.update(resultItem)
}
}
- formats = allFormats.first().toMutableList()
+ formats = allFormats.first().filter { !genericVideoFormats.contains(it) }.toMutableList()
UiUtil.populateFormatCard(requireContext(), formatCard, item.first().format, item.first().audioFormats)
}
}
formatCard.setOnClickListener{
if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
- val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats), listener)
+ val bottomSheet = FormatSelectionBottomSheetDialog(listOf(downloadItem), listOf(formats.ifEmpty { genericVideoFormats }), listener)
bottomSheet.show(parentFragmentManager, "formatSheet")
}
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt
index a4446f48..77501afb 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/FormatSelectionBottomSheetDialog.kt
@@ -276,7 +276,7 @@ class FormatSelectionBottomSheetDialog(private val items: List, p
}
}
- for (i in finalFormats.lastIndex downTo 0){
+ for (i in 0.. finalFormats.lastIndex){
val format = finalFormats[i]
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
formatItem.tag = "${format.format_id}${format.format_note}"
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt
index 518e1fd2..f5ae52b5 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt
@@ -5,8 +5,6 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
-import android.os.Build.VERSION
-import android.os.Build.VERSION_CODES
import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings
@@ -29,7 +27,6 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
override val title: Int = R.string.general
private var language: ListPreference? = null
- private var language13: Preference? = null
private var theme: ListPreference? = null
private var accent: ListPreference? = null
private var highContrast: SwitchPreferenceCompat? = null
@@ -51,45 +48,28 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
}
language = findPreference("app_language")
- language13 = findPreference("app_language_13")
theme = findPreference("ytdlnis_theme")
accent = findPreference("theme_accent")
highContrast = findPreference("high_contrast")
locale = findPreference("locale")
showTerminalShareIcon = findPreference("show_terminal")
- if(VERSION.SDK_INT < VERSION_CODES.TIRAMISU){
- val values = resources.getStringArray(R.array.language_values)
- val entries = mutableListOf()
- values.forEach {
- entries.add(Locale(it).getDisplayName(Locale(it)))
- }
- language!!.entries = entries.toTypedArray()
+ val values = resources.getStringArray(R.array.language_values)
+ val entries = mutableListOf()
+ values.forEach {
+ entries.add(Locale(it).getDisplayName(Locale(it)))
+ }
+ language!!.entries = entries.toTypedArray()
- if(language!!.value == null) language!!.value = Locale.getDefault().language
- language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value))
+ if(language!!.value == null) language!!.value = Locale.getDefault().language
+ language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value))
- language!!.onPreferenceChangeListener =
- Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
- language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString()))
- AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString()))
- true
- }
-
- language13?.isVisible = false
- }else{
- language?.isVisible = false
- language13?.isVisible = true
- language13?.summary = Locale.getDefault().displayLanguage
-
- language13!!.setOnPreferenceClickListener {
- val intent = Intent(Settings.ACTION_APP_LOCALE_SETTINGS)
- intent.data = Uri.fromParts("package", requireActivity().packageName, null)
- requireActivity().startActivity(intent)
- requireActivity().finishAffinity()
+ language!!.onPreferenceChangeListener =
+ Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
+ language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString()))
+ AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString()))
true
}
- }
theme!!.summary = theme!!.entry
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt
index 8d83519e..53167599 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt
@@ -2,11 +2,13 @@ package com.deniscerri.ytdlnis.util
import android.content.Context
import android.content.SharedPreferences
+import android.content.res.Resources
import android.os.Looper
import android.text.Html
import android.util.Log
import android.util.Patterns
import android.widget.Toast
+import androidx.preference.AndroidResources
import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.ChapterItem
@@ -32,7 +34,6 @@ import java.util.regex.Pattern
class InfoUtil(private val context: Context) {
- private var items: ArrayList
private lateinit var sharedPreferences: SharedPreferences
init {
@@ -43,12 +44,10 @@ class InfoUtil(private val context: Context) {
} catch (e: Exception) {
e.printStackTrace()
}
- items = ArrayList()
}
fun search(query: String): ArrayList {
- items = ArrayList()
return when(sharedPreferences.getString("search_engine", "ytsearch")){
"ytsearch" -> try{
searchFromPiped(query)
@@ -68,6 +67,7 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class)
fun searchFromPiped(query: String): ArrayList {
+ val items = arrayListOf()
val data = genericRequest("$pipedURL/search?q=$query&filter=videos®ion=${countryCODE}")
val dataArray = data.getJSONArray("items")
if (dataArray.length() == 0) return getFromYTDL(query)
@@ -86,6 +86,7 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class)
fun searchFromPipedMusic(query: String): ArrayList {
+ val items = arrayListOf()
val data = genericRequest("$pipedURL/search?q=$query=&filter=music_songs®ion=${countryCODE}")
val dataArray = data.getJSONArray("items")
if (dataArray.length() == 0) return getFromYTDL(query)
@@ -105,7 +106,7 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class)
fun getPlaylist(id: String, nextPageToken: String): PlaylistTuple {
try{
- items = ArrayList()
+ val items = arrayListOf()
// -------------- PIPED API FUNCTION -------------------
var url = ""
url = if (nextPageToken.isBlank()) "$pipedURL/playlists/$id"
@@ -226,7 +227,6 @@ class InfoUtil(private val context: Context) {
}
}
- formats.sortBy { it.filesize }
formats.groupBy { it.format_id }.forEach {
if (it.value.count() > 1) {
it.value.filter { f-> !f.format_note.contains("original", true) }.forEachIndexed { index, format -> format.format_id = format.format_id.split("-")[0] + "-${index}" }
@@ -234,6 +234,7 @@ class InfoUtil(private val context: Context) {
engDefault?.format_id = (engDefault?.format_id?.split("-")?.get(0) ?: "") + "-${it.value.size-1}"
}
}
+ formats.sortByDescending { it.filesize }
}
val chapters = ArrayList()
@@ -350,7 +351,6 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class)
fun getTrending(): ArrayList {
- items = ArrayList()
if (sharedPreferences.getString("api_key", "")!!.isNotBlank()){
return getTrendingFromYoutubeAPI()
}
@@ -359,8 +359,8 @@ class InfoUtil(private val context: Context) {
@Throws(JSONException::class)
fun getTrendingFromYoutubeAPI(): ArrayList {
+ val items = arrayListOf()
val key = sharedPreferences.getString("api_key", "")!!
-
val url = "https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&videoCategoryId=10®ionCode=$countryCODE&maxResults=25&key=$key"
//short data
val res = genericRequest(url)
@@ -389,6 +389,7 @@ class InfoUtil(private val context: Context) {
}
private fun getTrendingFromPiped(): ArrayList {
+ val items = arrayListOf()
val url = "$pipedURL/trending?region=$countryCODE"
val res = genericArrayRequest(url)
try {
@@ -547,7 +548,7 @@ class InfoUtil(private val context: Context) {
}
fun getFromYTDL(query: String): ArrayList {
- items = ArrayList()
+ val items = arrayListOf()
val searchEngine = sharedPreferences.getString("search_engine", "ytsearch")
try {
val request : YoutubeDLRequest
@@ -583,12 +584,12 @@ class InfoUtil(private val context: Context) {
}
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
- val results: Array = try {
+ val results: List = try {
val lineSeparator = System.getProperty("line.separator")
- youtubeDLResponse.out.split(lineSeparator!!).toTypedArray()
+ youtubeDLResponse.out.split(lineSeparator!!)
} catch (e: Exception) {
- arrayOf(youtubeDLResponse.out)
- }
+ listOf(youtubeDLResponse.out)
+ }.filter { it.isNotBlank() }
for (result in results) {
if (result.isNullOrBlank()) continue
val jsonObject = JSONObject(result)
@@ -690,7 +691,7 @@ class InfoUtil(private val context: Context) {
val formats = arrayListOf()
if (formatsInJSON != null) {
- for (f in 0 until formatsInJSON.length()){
+ for (f in formatsInJSON.length() - 1 downTo 0){
val format = formatsInJSON.getJSONObject(f)
if (format.has("filesize")){
if (format.get("filesize") == "None"){
@@ -987,8 +988,9 @@ class InfoUtil(private val context: Context) {
val limitRate = sharedPreferences.getString("limit_rate", "")
if (limitRate != "") request.addOption("-r", limitRate!!)
- request.addOption("--trim-filenames", 120)
if(downloadItem.type != DownloadViewModel.Type.command){
+ request.addOption("--trim-filenames", 120)
+
if (downloadItem.SaveThumb) {
request.addOption("--write-thumbnail")
request.addOption("--convert-thumbnails", "jpg")
@@ -1024,6 +1026,7 @@ class InfoUtil(private val context: Context) {
request.addCommands(listOf("--replace-in-metadata", "title", ".+", downloadItem.title))
}
if (downloadItem.author.isNotBlank()){
+ request.addOption("--parse-metadata", "%(artist,uploader,creator,channel|null)s:%(uploader)s")
request.addCommands(listOf("--replace-in-metadata", "uploader", ".+", downloadItem.author))
request.addCommands(listOf("--replace-in-metadata","uploader"," - Topic$",""))
}
@@ -1078,7 +1081,7 @@ class InfoUtil(private val context: Context) {
}
}
-
+ downloadItem.customFileNameTemplate = downloadItem.customFileNameTemplate.replace("%(uploader)s", "%(uploader,channel)s")
}
if (sharedPreferences.getBoolean("restrict_filenames", true)) {
@@ -1166,10 +1169,6 @@ class InfoUtil(private val context: Context) {
DownloadViewModel.Type.video -> {
val supportedContainers = context.resources.getStringArray(R.array.video_containers)
- if (!sharedPreferences.getBoolean("embed_metadata", true)){
- request.addOption("--no-embed-metadata")
- }
-
if (downloadItem.videoPreferences.addChapters) {
if (sharedPreferences.getBoolean("use_sponsorblock", true)){
request.addOption("--sponsorblock-mark", "all")
@@ -1200,100 +1199,102 @@ class InfoUtil(private val context: Context) {
}
//format logic
-
- val defaultFormats = context.resources.getStringArray(R.array.video_formats_values)
- var usingGenericFormat = false
-
var videof = downloadItem.format.format_id
- if (videof == context.resources.getString(R.string.best_quality) || videof == "best") {
- videof = "bestvideo"
- usingGenericFormat = true
- }else if (videof == context.resources.getString(R.string.worst_quality) || videof == "worst") {
- videof = "worst"
- }else if (defaultFormats.contains(videof)) {
- videof = "bestvideo[height<="+videof.split("_")[0].dropLast(1)+"]"
- }
-
- val preferredFormatIDs = sharedPreferences.getString("format_id", "").toString()
- .split(",")
- .filter { it.isNotEmpty() }
- .ifEmpty { listOf(videof) }
-
- var audiof = "bestaudio"
+ var audiof = "ba"
if (downloadItem.videoPreferences.audioFormatIDs.isNotEmpty()){
audiof = downloadItem.videoPreferences.audioFormatIDs.joinToString("+")
}
if (downloadItem.videoPreferences.removeAudio) audiof = ""
- val preferredAudioFormatIDs = sharedPreferences.getString("format_id_audio", "")
- .toString()
- .split(",")
- .filter { it.isNotEmpty() }
- .ifEmpty { listOf(audiof) }
-
- val preferredVideoFormats = if (usingGenericFormat) preferredFormatIDs else listOf(videof)
- val preferredAudioFormats = if (usingGenericFormat && downloadItem.videoPreferences.audioFormatIDs.isEmpty()) {
- preferredAudioFormatIDs
- } else listOf(audiof)
-
- if (preferredAudioFormats.any{it.contains("+")}){
- request.addOption("--audio-multistreams")
- }
-
- val preferredCodec = sharedPreferences.getString("video_codec", "")
- val extPref = if (cont.isNotBlank()) "[ext=$cont]" else ""
- val vCodecPref = if (preferredCodec!!.isNotBlank()) "[vcodec^=$preferredCodec]" else ""
-
+ 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()
- //build format with extension and vcodec
- preferredVideoFormats.forEach { v ->
- preferredAudioFormats.forEach { a ->
- val aa = if (a.isNotBlank()) "+$a" else ""
- f.append("$v$extPref$vCodecPref$aa/")
- }
- }
+ if(!usingGenericFormat){
+ val aa = if (audiof.isNotBlank()) "+$audiof" else ""
+ f.append("$videof$aa/$videof/best")
- //build format with vcodec
- if (extPref.isNotBlank()){
- preferredVideoFormats.forEach { v ->
+ if (audiof.contains("+")){
+ request.addOption("--audio-multistreams")
+ }
+ }else{
+ if (videof == context.resources.getString(R.string.best_quality) || videof == "best") {
+ videof = "bv"
+ }else if (videof == context.resources.getString(R.string.worst_quality) || videof == "worst") {
+ videof = "worst"
+ }else if (defaultFormats.contains(videof)) {
+ videof = "bv[height<="+videof.split("_")[0].dropLast(1)+"]"
+ }
+
+ val preferredFormatIDs = sharedPreferences.getString("format_id", "").toString()
+ .split(",")
+ .filter { it.isNotEmpty() }
+ .ifEmpty { listOf(videof) }.toMutableList()
+ if (!preferredFormatIDs.contains(videof)){
+ preferredFormatIDs.add(0, videof)
+ }
+
+ val preferredAudioFormatIDs = sharedPreferences.getString("format_id_audio", "")
+ .toString()
+ .split(",")
+ .filter { it.isNotEmpty() }
+ .ifEmpty { listOf(audiof) }
+
+ val preferredAudioFormats = if (downloadItem.videoPreferences.audioFormatIDs.isEmpty()) {
+ preferredAudioFormatIDs
+ } else listOf(audiof)
+
+ if (preferredAudioFormats.any{it.contains("+")}){
+ request.addOption("--audio-multistreams")
+ }
+
+ val preferredCodec = sharedPreferences.getString("video_codec", "")
+ val extPref = if (cont.isNotBlank()) "[ext=$cont]" else ""
+ val vCodecPref = if (preferredCodec!!.isNotBlank()) "[vcodec~='^($preferredCodec)']" else ""
+
+
+ preferredFormatIDs.forEach { v ->
+ //build format with extension and vcodec
preferredAudioFormats.forEach { a ->
val aa = if (a.isNotBlank()) "+$a" else ""
- f.append("$videof$vCodecPref$aa/")
+ f.append("$v$extPref$vCodecPref$aa/")
}
- }
- }
- if (vCodecPref.isNotBlank()){
- preferredVideoFormats.forEach { v ->
//build format with vcodec
- preferredAudioFormats.forEach {a ->
- val aa = if (a.isNotBlank()) "+$a" else ""
- f.append("$v$aa/")
+ if (extPref.isNotBlank()){
+ preferredAudioFormats.forEach { a ->
+ val aa = if (a.isNotBlank()) "+$a" else ""
+ f.append("$v$vCodecPref$aa/")
+ }
}
- }
- }
- if (!downloadItem.videoPreferences.removeAudio){
- //build format with best audio
- preferredVideoFormats.forEach { v ->
- if(!f.contains("$v+bestaudio/")){
- f.append("$v+bestaudio/")
+ //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){
+ //build format with best audio
+ if(!f.contains("$v+ba/")){
+ f.append("$v+ba/")
+ }
+
+ //build formats with standalone video
+ if(!f.contains("/$v/")){
+ f.append("$v/")
+ }
}
}
- //build formats with standalone video
- preferredVideoFormats.forEach { v ->
- if(!f.contains("/$v/")){
- f.append("$v/")
- }
+ if(!f.endsWith("best/")){
+ //last fallback
+ f.append("best")
}
}
- if(!f.endsWith("best/")){
- //last fallback
- f.append("best")
- }
request.addOption("-f", f.toString().replace("/$".toRegex(), ""))
@@ -1302,8 +1303,10 @@ class InfoUtil(private val context: Context) {
request.addOption("--write-subs")
request.addOption("--write-auto-subs")
- request.addOption("--sub-format", "${subFormat}/best")
- request.addOption("--convert-subtitles", subFormat ?: "srt")
+ if(subFormat!!.isNotBlank()){
+ request.addOption("--sub-format", "${subFormat}/best")
+ request.addOption("--convert-subtitles", subFormat ?: "srt")
+ }
if (!downloadItem.videoPreferences.embedSubs) {
request.addOption("--sub-langs", downloadItem.videoPreferences.subsLanguages.ifEmpty { "en.*,.*-orig" })
}
@@ -1368,6 +1371,27 @@ class InfoUtil(private val context: Context) {
return final
}
+ fun getGenericAudioFormats(resources: Resources) : MutableList{
+ val audioFormatIDPreference = sharedPreferences.getString("format_id_audio", "").toString().split(",").filter { it.isNotEmpty() }
+ val audioFormats = resources.getStringArray(R.array.audio_formats)
+ val formats = mutableListOf()
+ val containerPreference = sharedPreferences.getString("audio_format", "")
+ audioFormats.reversed().forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
+ audioFormatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"","", "",1, it)) }
+ return formats
+ }
+
+ fun getGenericVideoFormats(resources: Resources) : MutableList{
+ val formatIDPreference = sharedPreferences.getString("format_id", "").toString().split(",").filter { it.isNotEmpty() }
+
+ val videoFormats = resources.getStringArray(R.array.video_formats_values)
+ val formats = mutableListOf()
+ val containerPreference = sharedPreferences.getString("video_format", "")
+ videoFormats.reversed().forEach { formats.add(Format(it, containerPreference!!,"Default","", "",0, it.split("_")[0])) }
+ formatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",1, it)) }
+ return formats
+ }
+
private val pipedURL = sharedPreferences.getString("piped_instance", defaultPipedURL)?.ifEmpty { defaultPipedURL }?.removeSuffix("/")
class PlaylistTuple internal constructor(
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt
index 44d50a81..2876a6ab 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt
@@ -34,11 +34,18 @@ class NotificationUtil(var context: Context) {
NotificationManager::class.java
)
- //gui downloads
- var name: CharSequence = context.getString(R.string.download_notification_channel_name)
- var description = context.getString(R.string.download_notification_channel_description)
+ //downloading worker notification
+ var name: CharSequence = context.getString(R.string.downloading)
+ var description = "WorkManager Default Notification"
val importance = NotificationManager.IMPORTANCE_LOW
- var channel = NotificationChannel(DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
+ var channel = NotificationChannel(DOWNLOAD_WORKER_CHANNEL_ID, name, importance)
+ channel.description = description
+ notificationManager.createNotificationChannel(channel)
+
+ //gui downloads
+ name = context.getString(R.string.download_notification_channel_name)
+ description = context.getString(R.string.download_notification_channel_description)
+ channel = NotificationChannel(DOWNLOAD_SERVICE_CHANNEL_ID, name, importance)
channel.description = description
notificationManager.createNotificationChannel(channel)
@@ -77,7 +84,7 @@ class NotificationUtil(var context: Context) {
}
fun createDefaultWorkerNotification() : Notification {
- val notificationBuilder = getBuilder(DOWNLOAD_SERVICE_CHANNEL_ID)
+ val notificationBuilder = getBuilder(DOWNLOAD_WORKER_CHANNEL_ID)
return notificationBuilder
.setContentTitle(context.getString(R.string.downloading))
@@ -480,6 +487,7 @@ class NotificationUtil(var context: Context) {
const val FORMAT_UPDATING_FINISHED_NOTIFICATION_ID = 7
const val DOWNLOAD_MISC_CHANNEL_ID = "4"
const val DOWNLOAD_MISC_NOTIFICATION_ID = 4
+ const val DOWNLOAD_WORKER_CHANNEL_ID = "5"
private const val PROGRESS_MAX = 100
private const val PROGRESS_CURR = 0
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt
index ecf6f52e..19e87b2c 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UpdateUtil.kt
@@ -57,16 +57,13 @@ class UpdateUtil(var context: Context) {
v = res.first { !it.tag_name.contains("beta", true) }
}
- val current = BuildConfig.VERSION_NAME.replace("-beta", "").replace(".", "").toInt()
- val incoming = v.tag_name.removePrefix("v").replace("-beta", "").replace(".", "").toInt()
+ val current = BuildConfig.VERSION_NAME.replace("-beta", "").replace(".", "").padEnd(10,'0').toInt()
+ val incoming = v.tag_name.removePrefix("v").replace("-beta", "").replace(".", "").padEnd(10,'0').toInt()
- Log.e("aa", current.toString())
- Log.e("aa", incoming.toString())
var isInLatest = true
- if ((BuildConfig.VERSION_NAME.contains("beta", true) && !useBeta) ||
- (!BuildConfig.VERSION_NAME.contains("beta", true) && useBeta) ||
- current < incoming ){
+ if ((current < incoming) ||
+ (current > incoming && BuildConfig.VERSION_NAME.contains("beta", true) && !useBeta)){
isInLatest = false
}
diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt
index e328d647..84a39a53 100644
--- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt
+++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt
@@ -1,8 +1,11 @@
package com.deniscerri.ytdlnis.work
import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
import android.os.Handler
import android.os.Looper
+import android.util.DisplayMetrics
import android.util.Log
import android.widget.Toast
import androidx.navigation.NavDeepLinkBuilder
@@ -35,6 +38,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.io.File
+import java.util.Locale
import kotlin.random.Random
@@ -60,6 +64,12 @@ class DownloadWorker(
val currentWork = WorkManager.getInstance(context).getWorkInfosByTag("download").await()
if (currentWork.count{it.state == WorkInfo.State.RUNNING} > 1) return Result.success()
+ val confTmp = Configuration(context.resources.configuration)
+ val currLang = sharedPreferences.getString("app_language", "en")!!.split("-")
+ confTmp.setLocale(if (currLang.size == 1) Locale(currLang[0]) else Locale(currLang[0], currLang[1]))
+ val metrics = DisplayMetrics()
+ val resources = Resources(context.assets, metrics, confTmp)
+
val pendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.downloadQueueMainFragment)
@@ -162,8 +172,10 @@ class DownloadWorker(
.sortedByDescending { it.length() }
.map { it.absolutePath }
.toList()
-
FileUtil.scanMedia(finalPaths, context)
+ if (finalPaths.isEmpty()){
+ finalPaths = listOf(context.getString(R.string.unfound_file))
+ }
}else{
//move file from internal to set download directory
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id))
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index d2e2a5d7..724a05c8 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -48,7 +48,7 @@
- worst
- - 360p
+ - 360p_ytdlnisgeneric
- 480p_ytdlnisgeneric
- 720p_ytdlnisgeneric
- 1080p_ytdlnisgeneric
@@ -766,6 +766,15 @@
+ - @string/defaultValue
+ - srt
+ - ass
+ - lrc
+ - vtt
+
+
+
+
- srt
- ass
- lrc
@@ -794,9 +803,9 @@
- - av0
- - vp
- - avc
- - hev
+ - av[01]
+ - vp[09]
+ - avc|h264
+ - hev|h265
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5db9503c..8eee5618 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -292,7 +292,7 @@
Extra Command
Use Cookies
Embed Metadata
- Embed metadata to the video file. Also embeds chapters/infojson if present
+ Embed and parse metadata to the audio file.
Update Formats in Background
Auto-Update yt-dlp
Use SponsorBlock
diff --git a/app/src/main/res/xml/general_preferences.xml b/app/src/main/res/xml/general_preferences.xml
index d1d181d5..062acb33 100644
--- a/app/src/main/res/xml/general_preferences.xml
+++ b/app/src/main/res/xml/general_preferences.xml
@@ -11,13 +11,6 @@
app:summary="en"
app:title="@string/language" />
-
-
-