Add ability to preview filename template
This commit is contained in:
parent
488b2d6312
commit
eaa2e1e4fd
10 changed files with 161 additions and 23 deletions
|
|
@ -27,4 +27,8 @@ class YTDLPViewModel(private val application: Application) : AndroidViewModel(ap
|
|||
fun getVersion(channel: String) : String {
|
||||
return ytdlpUtil.getVersion(application, channel)
|
||||
}
|
||||
|
||||
fun getFilenameTemplatePreview(item: DownloadItem, filenameTemplate: String) : String {
|
||||
return ytdlpUtil.getFilenameTemplatePreview(item, filenameTemplate)
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
|||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel.Type
|
||||
import com.deniscerri.ytdl.database.viewmodel.FormatViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
|
||||
import com.deniscerri.ytdl.util.Extensions.applyFilenameTemplateForCuts
|
||||
import com.deniscerri.ytdl.util.FileUtil
|
||||
import com.deniscerri.ytdl.util.FormatUtil
|
||||
|
|
@ -57,6 +58,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
private var activity: Activity? = null
|
||||
private lateinit var downloadViewModel : DownloadViewModel
|
||||
private lateinit var resultViewModel : ResultViewModel
|
||||
private lateinit var ytdlpViewModel : YTDLPViewModel
|
||||
private lateinit var formatViewModel : FormatViewModel
|
||||
private lateinit var saveDir : TextInputLayout
|
||||
private lateinit var freeSpace : TextView
|
||||
|
|
@ -80,6 +82,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
activity = getActivity()
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
|
||||
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
|
||||
genericAudioFormats = FormatUtil(requireContext()).getGenericAudioFormats(requireContext().resources)
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
|
@ -310,6 +313,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
UiUtil.configureAudio(
|
||||
view,
|
||||
requireActivity(),
|
||||
ytdlpViewModel,
|
||||
listOf(downloadItem),
|
||||
embedThumbClicked = {
|
||||
downloadItem.audioPreferences.embedThumb = it
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
|||
import com.deniscerri.ytdl.database.viewmodel.FormatViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
|
||||
import com.deniscerri.ytdl.receiver.ShareActivity
|
||||
import com.deniscerri.ytdl.ui.BaseActivity
|
||||
import com.deniscerri.ytdl.ui.adapter.ConfigureMultipleDownloadsAdapter
|
||||
|
|
@ -83,6 +84,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
private lateinit var historyViewModel: HistoryViewModel
|
||||
private lateinit var commandTemplateViewModel: CommandTemplateViewModel
|
||||
private lateinit var resultViewModel: ResultViewModel
|
||||
private lateinit var ytdlpViewModel: YTDLPViewModel
|
||||
private lateinit var formatViewModel: FormatViewModel
|
||||
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
|
|
@ -121,6 +123,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
|
||||
historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
|
||||
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
|
||||
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
|
||||
commandTemplateViewModel = ViewModelProvider(requireActivity())[CommandTemplateViewModel::class.java]
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
|
@ -539,6 +542,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
UiUtil.configureAudio(
|
||||
sheetView,
|
||||
requireActivity(),
|
||||
ytdlpViewModel,
|
||||
items,
|
||||
embedThumbClicked = {enabled ->
|
||||
items.forEach {
|
||||
|
|
@ -631,6 +635,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
UiUtil.configureVideo(
|
||||
sheetView,
|
||||
requireActivity(),
|
||||
ytdlpViewModel,
|
||||
items,
|
||||
embedSubsClicked = {checked ->
|
||||
items.forEach { it.videoPreferences.embedSubs = checked }
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
|||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel.Type
|
||||
import com.deniscerri.ytdl.database.viewmodel.FormatViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
|
||||
import com.deniscerri.ytdl.util.Extensions.applyFilenameTemplateForCuts
|
||||
import com.deniscerri.ytdl.util.FileUtil
|
||||
import com.deniscerri.ytdl.util.FormatUtil
|
||||
|
|
@ -59,6 +60,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
private lateinit var downloadViewModel : DownloadViewModel
|
||||
private lateinit var formatViewModel : FormatViewModel
|
||||
private lateinit var resultViewModel: ResultViewModel
|
||||
private lateinit var ytdlpViewModel: YTDLPViewModel
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var shownFields: List<String>
|
||||
lateinit var title : TextInputLayout
|
||||
|
|
@ -85,6 +87,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
|
||||
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
|
||||
val formatUtil = FormatUtil(requireContext())
|
||||
genericVideoFormats = formatUtil.getGenericVideoFormats(requireContext().resources)
|
||||
genericAudioFormats = formatUtil.getGenericAudioFormats(requireContext().resources)
|
||||
|
|
@ -353,6 +356,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
UiUtil.configureVideo(
|
||||
view,
|
||||
requireActivity(),
|
||||
ytdlpViewModel,
|
||||
listOf(downloadItem),
|
||||
embedSubsClicked = {
|
||||
downloadItem.videoPreferences.embedSubs = it
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
|||
audioFilenameTemplate?.summary = preferences.getString("file_name_template_audio", "%(uploader).30B - %(title).170B")
|
||||
|
||||
videoFilenameTemplate?.setOnPreferenceClickListener {
|
||||
UiUtil.showFilenameTemplateDialog(requireActivity(), videoFilenameTemplate?.summary.toString() ?: "", "${getString(R.string.file_name_template)} [${getString(R.string.video)}]") {
|
||||
UiUtil.showFilenameTemplateDialog(requireActivity(),videoFilenameTemplate?.summary.toString() ?: "", "${getString(R.string.file_name_template)} [${getString(R.string.video)}]") {
|
||||
editor.putString("file_name_template", it).apply()
|
||||
videoFilenameTemplate?.summary = it
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import android.content.SharedPreferences
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Looper
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.text.format.DateFormat
|
||||
|
|
@ -35,6 +36,7 @@ import android.widget.CheckBox
|
|||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
|
|
@ -105,6 +107,7 @@ import java.io.File
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.logging.Handler
|
||||
|
||||
|
||||
object UiUtil {
|
||||
|
|
@ -1302,6 +1305,7 @@ object UiUtil {
|
|||
fun configureVideo(
|
||||
view: View,
|
||||
context: Activity,
|
||||
ytdlpViewModel: YTDLPViewModel,
|
||||
items: List<DownloadItem>,
|
||||
embedSubsClicked : (Boolean) -> Unit,
|
||||
addChaptersClicked: (Boolean) -> Unit,
|
||||
|
|
@ -1764,7 +1768,8 @@ object UiUtil {
|
|||
}else {
|
||||
""
|
||||
}
|
||||
showFilenameTemplateDialog(context, currentFilename) {
|
||||
val itemContext = if (items.size == 1) items.first() else null
|
||||
showFilenameTemplateDialog(context, currentFilename, ytdlpViewModel = ytdlpViewModel, itemContext = itemContext) {
|
||||
filenameTemplateSet(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -1791,6 +1796,7 @@ object UiUtil {
|
|||
fun configureAudio(
|
||||
view: View,
|
||||
context: Activity,
|
||||
ytdlpViewModel: YTDLPViewModel,
|
||||
items: List<DownloadItem>,
|
||||
embedThumbClicked: (Boolean) -> Unit,
|
||||
cropThumbClicked: (Boolean) -> Unit,
|
||||
|
|
@ -1867,7 +1873,8 @@ object UiUtil {
|
|||
}else {
|
||||
""
|
||||
}
|
||||
showFilenameTemplateDialog(context, currentFilename) {
|
||||
val itemContext = if (items.size == 1) items.first() else null
|
||||
showFilenameTemplateDialog(context, currentFilename, ytdlpViewModel = ytdlpViewModel, itemContext = itemContext) {
|
||||
filenameTemplateSet(it)
|
||||
}
|
||||
}
|
||||
|
|
@ -2103,7 +2110,7 @@ object UiUtil {
|
|||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun showFilenameTemplateDialog(context: Activity, currentFilename: String, dialogTitle: String = context.getString(R.string.file_name_template), filenameSelected: (f: String) -> Unit){
|
||||
fun showFilenameTemplateDialog(context: Activity, currentFilename: String, dialogTitle: String = context.getString(R.string.file_name_template), ytdlpViewModel: YTDLPViewModel? = null, itemContext: DownloadItem? = null, filenameSelected: (f: String) -> Unit){
|
||||
val builder = MaterialAlertDialogBuilder(context)
|
||||
builder.setTitle(dialogTitle)
|
||||
val view = context.layoutInflater.inflate(R.layout.filename_template_dialog, null)
|
||||
|
|
@ -2174,6 +2181,42 @@ object UiUtil {
|
|||
myTemplatesView.isVisible = true
|
||||
}
|
||||
|
||||
view.findViewById<MaterialCardView>(R.id.filename_template_preview).isVisible = itemContext != null
|
||||
val previewTemplateBtn = view.findViewById<MaterialButton>(R.id.filename_template_preview_btn)
|
||||
val previewTemplateLoading = view.findViewById<ProgressBar>(R.id.filename_template_preview_loading)
|
||||
val previewTemplateText = view.findViewById<TextView>(R.id.filename_template_preview_text)
|
||||
|
||||
previewTemplateBtn.setOnClickListener {
|
||||
previewTemplateLoading.isVisible = true
|
||||
previewTemplateBtn.isVisible = false
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val preview = ytdlpViewModel!!.getFilenameTemplatePreview(itemContext!!, editText.text.toString())
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
previewTemplateLoading.isVisible = false
|
||||
previewTemplateText.isVisible = true
|
||||
previewTemplateText.text = preview
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editText.addTextChangedListener(object : TextWatcher {
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
previewTemplateText.isVisible = false
|
||||
previewTemplateLoading.isVisible = false
|
||||
previewTemplateBtn.isVisible = true
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun afterTextChanged(s: Editable?) {}
|
||||
})
|
||||
|
||||
if (currentFilename.isNotBlank() && itemContext != null) {
|
||||
previewTemplateBtn.isVisible = true
|
||||
previewTemplateBtn.performClick()
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
//handle personal template chips
|
||||
val mychips = mutableListOf<Chip>()
|
||||
|
|
@ -2220,7 +2263,6 @@ object UiUtil {
|
|||
chips.add(tmp)
|
||||
}
|
||||
|
||||
|
||||
withContext(Dispatchers.Main){
|
||||
if (mychips.isNotEmpty()){
|
||||
myTemplatesView.isVisible = true
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ import org.json.JSONArray
|
|||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.lang.reflect.Type
|
||||
import java.security.MessageDigest
|
||||
import java.util.Base64
|
||||
import java.util.Locale
|
||||
import java.util.StringJoiner
|
||||
import java.util.UUID
|
||||
|
|
@ -118,6 +120,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
}else{
|
||||
request = YoutubeDLRequest(query)
|
||||
}
|
||||
request.addWriteInfoJson(query)
|
||||
}else{
|
||||
request = YoutubeDLRequest(emptyList())
|
||||
when (searchEngine){
|
||||
|
|
@ -374,6 +377,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
return parseYTDLPListResults(results)
|
||||
}
|
||||
|
||||
|
||||
suspend fun getFormatsForAll(urls: List<String>, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result<MutableList<MutableList<Format>>> {
|
||||
val formatCollection = mutableListOf<MutableList<Format>>()
|
||||
|
||||
|
|
@ -456,7 +460,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
return Result.success(formatCollection)
|
||||
}
|
||||
|
||||
|
||||
fun getFormats(url: String) : List<Format> {
|
||||
val request = YoutubeDLRequest(url)
|
||||
request.addOption("--print", "%(formats)s")
|
||||
|
|
@ -583,7 +586,51 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
return Result.failure(e)
|
||||
}
|
||||
}
|
||||
fun getVersion(context: Context, channel: String) : String {
|
||||
if (listOf("stable", "nightly", "master").contains(channel)) {
|
||||
return YoutubeDL.version(context) ?: ""
|
||||
}
|
||||
|
||||
val req = YoutubeDLRequest(emptyList())
|
||||
req.addOption("--version")
|
||||
return YoutubeDL.getInstance().execute(req).out.trim()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun YoutubeDLRequest.addWriteInfoJson(url: String) {
|
||||
val cachePath = "${FileUtil.getCachePath(context)}infojsons"
|
||||
val infoJsonName = MessageDigest.getInstance("MD5").digest(url.toByteArray()).toHexString()
|
||||
this.addCommands(listOf("--print-to-file", "video:%()#j", "${cachePath}/${infoJsonName}.info.json"))
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun getInfoJsonPath(url: String): String? {
|
||||
val cachePath = "${FileUtil.getCachePath(context)}infojsons"
|
||||
val infoJsonName = MessageDigest.getInstance("MD5").digest(url.toByteArray()).toHexString()
|
||||
val infoJsonFile = File(cachePath).walkTopDown().firstOrNull { it.name == "${infoJsonName}.info.json" }
|
||||
return infoJsonFile?.absolutePath
|
||||
}
|
||||
|
||||
fun getFilenameTemplatePreview(item: DownloadItem, filenameTemplate: String): String {
|
||||
item.customFileNameTemplate = filenameTemplate
|
||||
val request = buildYoutubeDLRequest(item)
|
||||
request.addOption("--print", "%(filename)s")
|
||||
request.addOption("--skip-download")
|
||||
|
||||
val infoJsonPath = getInfoJsonPath(item.url)
|
||||
if (infoJsonPath == null) {
|
||||
request.addWriteInfoJson(item.url)
|
||||
} else {
|
||||
request.addOption("--load-info-json", infoJsonPath)
|
||||
}
|
||||
|
||||
try {
|
||||
val response = YoutubeDL.execute(request)
|
||||
return response.out.replace(FileUtil.getCachePath(context) + "${item.id}/", "").trim()
|
||||
} catch (ex: Exception) {
|
||||
return ex.message ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
fun parseYTDLRequestString(request : YoutubeDLRequest) : String {
|
||||
val arr = request.buildCommand().toMutableList()
|
||||
|
|
@ -616,15 +663,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
}
|
||||
}
|
||||
|
||||
fun getVersion(context: Context, channel: String) : String {
|
||||
if (listOf("stable", "nightly", "master").contains(channel)) {
|
||||
return YoutubeDL.version(context) ?: ""
|
||||
}
|
||||
|
||||
val req = YoutubeDLRequest(emptyList())
|
||||
req.addOption("--version")
|
||||
return YoutubeDL.getInstance().execute(req).out.trim()
|
||||
}
|
||||
|
||||
private fun YoutubeDLRequest.setYoutubeExtractorArgs(url: String?) {
|
||||
val extractorArgs = mutableListOf<String>()
|
||||
|
|
@ -858,11 +896,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
|
|||
request.addOption("--proxy", proxy)
|
||||
}
|
||||
|
||||
val updateYTDLP = sharedPreferences.getBoolean("update_ytdlp_while_downloading", false)
|
||||
if (updateYTDLP) {
|
||||
request.addOption("-U")
|
||||
}
|
||||
|
||||
val keepCache = sharedPreferences.getBoolean("keep_cache", false)
|
||||
if(keepCache){
|
||||
request.addOption("--keep-fragments")
|
||||
|
|
|
|||
|
|
@ -169,6 +169,12 @@ class DownloadWorker(
|
|||
val noCache = writtenPath || (!sharedPreferences.getBoolean("cache_downloads", true) && File(FileUtil.formatPath(downloadItem.downloadPath)).canWrite())
|
||||
|
||||
val request = ytdlpUtil.buildYoutubeDLRequest(downloadItem)
|
||||
|
||||
val updateYTDLP = sharedPreferences.getBoolean("update_ytdlp_while_downloading", false)
|
||||
if (updateYTDLP) {
|
||||
request.addOption("-U")
|
||||
}
|
||||
|
||||
downloadItem.status = DownloadRepository.Status.Active.toString()
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
delay(1500)
|
||||
|
|
@ -375,7 +381,6 @@ class DownloadWorker(
|
|||
FileUtil.deleteFile("${cachePath}/${infoJsonName}.info.json")
|
||||
}
|
||||
|
||||
|
||||
if (logDownloads){
|
||||
logRepo.update(it.message ?: "", logItem.id)
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:padding="10dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
|
@ -31,6 +31,46 @@
|
|||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/filename_template_preview"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/filename_template_preview_text"
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:gravity="center"
|
||||
android:textAlignment="textStart"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/filename_template_preview_loading"
|
||||
android:visibility="gone"
|
||||
android:layout_width="20dp"
|
||||
android:layout_margin="10dp"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
android:layout_height="20dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:id="@+id/filename_template_preview_btn"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/preview_filename"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/mytemplates"
|
||||
android:visibility="gone"
|
||||
|
|
|
|||
|
|
@ -504,4 +504,5 @@
|
|||
<string name="use_original_url_playlist_summary">Use playlist url given by user instead of the playlist_webpage_url tag from the json dump</string>
|
||||
<string name="update_ytdlp_while_downloading">Update yt-dlp while downloading</string>
|
||||
<string name="update_ytdlp_while_downloading_summary">Add -U to yt-dlp to update it to latest before downloading</string>
|
||||
<string name="preview_filename">Preview filename</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in a new issue