Add ability to preview filename template

pull/1026/head
deniscerri 7 months ago
parent 488b2d6312
commit eaa2e1e4fd
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -27,4 +27,8 @@ class YTDLPViewModel(private val application: Application) : AndroidViewModel(ap
fun getVersion(channel: String) : String { fun getVersion(channel: String) : String {
return ytdlpUtil.getVersion(application, channel) 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.DownloadViewModel.Type
import com.deniscerri.ytdl.database.viewmodel.FormatViewModel import com.deniscerri.ytdl.database.viewmodel.FormatViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel 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.Extensions.applyFilenameTemplateForCuts
import com.deniscerri.ytdl.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdl.util.FormatUtil import com.deniscerri.ytdl.util.FormatUtil
@ -57,6 +58,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
private var activity: Activity? = null private var activity: Activity? = null
private lateinit var downloadViewModel : DownloadViewModel private lateinit var downloadViewModel : DownloadViewModel
private lateinit var resultViewModel : ResultViewModel private lateinit var resultViewModel : ResultViewModel
private lateinit var ytdlpViewModel : YTDLPViewModel
private lateinit var formatViewModel : FormatViewModel private lateinit var formatViewModel : FormatViewModel
private lateinit var saveDir : TextInputLayout private lateinit var saveDir : TextInputLayout
private lateinit var freeSpace : TextView private lateinit var freeSpace : TextView
@ -80,6 +82,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
activity = getActivity() activity = getActivity()
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java] formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
genericAudioFormats = FormatUtil(requireContext()).getGenericAudioFormats(requireContext().resources) genericAudioFormats = FormatUtil(requireContext()).getGenericAudioFormats(requireContext().resources)
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
@ -310,6 +313,7 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
UiUtil.configureAudio( UiUtil.configureAudio(
view, view,
requireActivity(), requireActivity(),
ytdlpViewModel,
listOf(downloadItem), listOf(downloadItem),
embedThumbClicked = { embedThumbClicked = {
downloadItem.audioPreferences.embedThumb = it 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.FormatViewModel
import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel import com.deniscerri.ytdl.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
import com.deniscerri.ytdl.database.viewmodel.YTDLPViewModel
import com.deniscerri.ytdl.receiver.ShareActivity import com.deniscerri.ytdl.receiver.ShareActivity
import com.deniscerri.ytdl.ui.BaseActivity import com.deniscerri.ytdl.ui.BaseActivity
import com.deniscerri.ytdl.ui.adapter.ConfigureMultipleDownloadsAdapter import com.deniscerri.ytdl.ui.adapter.ConfigureMultipleDownloadsAdapter
@ -83,6 +84,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
private lateinit var historyViewModel: HistoryViewModel private lateinit var historyViewModel: HistoryViewModel
private lateinit var commandTemplateViewModel: CommandTemplateViewModel private lateinit var commandTemplateViewModel: CommandTemplateViewModel
private lateinit var resultViewModel: ResultViewModel private lateinit var resultViewModel: ResultViewModel
private lateinit var ytdlpViewModel: YTDLPViewModel
private lateinit var formatViewModel: FormatViewModel private lateinit var formatViewModel: FormatViewModel
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
private lateinit var recyclerView: RecyclerView private lateinit var recyclerView: RecyclerView
@ -121,6 +123,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java] historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java]
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java] resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java] formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
commandTemplateViewModel = ViewModelProvider(requireActivity())[CommandTemplateViewModel::class.java] commandTemplateViewModel = ViewModelProvider(requireActivity())[CommandTemplateViewModel::class.java]
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
@ -539,6 +542,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
UiUtil.configureAudio( UiUtil.configureAudio(
sheetView, sheetView,
requireActivity(), requireActivity(),
ytdlpViewModel,
items, items,
embedThumbClicked = {enabled -> embedThumbClicked = {enabled ->
items.forEach { items.forEach {
@ -631,6 +635,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
UiUtil.configureVideo( UiUtil.configureVideo(
sheetView, sheetView,
requireActivity(), requireActivity(),
ytdlpViewModel,
items, items,
embedSubsClicked = {checked -> embedSubsClicked = {checked ->
items.forEach { it.videoPreferences.embedSubs = 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.DownloadViewModel.Type
import com.deniscerri.ytdl.database.viewmodel.FormatViewModel import com.deniscerri.ytdl.database.viewmodel.FormatViewModel
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel 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.Extensions.applyFilenameTemplateForCuts
import com.deniscerri.ytdl.util.FileUtil import com.deniscerri.ytdl.util.FileUtil
import com.deniscerri.ytdl.util.FormatUtil 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 downloadViewModel : DownloadViewModel
private lateinit var formatViewModel : FormatViewModel private lateinit var formatViewModel : FormatViewModel
private lateinit var resultViewModel: ResultViewModel private lateinit var resultViewModel: ResultViewModel
private lateinit var ytdlpViewModel: YTDLPViewModel
private lateinit var preferences: SharedPreferences private lateinit var preferences: SharedPreferences
private lateinit var shownFields: List<String> private lateinit var shownFields: List<String>
lateinit var title : TextInputLayout lateinit var title : TextInputLayout
@ -85,6 +87,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java] resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java] formatViewModel = ViewModelProvider(requireActivity())[FormatViewModel::class.java]
ytdlpViewModel = ViewModelProvider(requireActivity())[YTDLPViewModel::class.java]
val formatUtil = FormatUtil(requireContext()) val formatUtil = FormatUtil(requireContext())
genericVideoFormats = formatUtil.getGenericVideoFormats(requireContext().resources) genericVideoFormats = formatUtil.getGenericVideoFormats(requireContext().resources)
genericAudioFormats = formatUtil.getGenericAudioFormats(requireContext().resources) genericAudioFormats = formatUtil.getGenericAudioFormats(requireContext().resources)
@ -353,6 +356,7 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
UiUtil.configureVideo( UiUtil.configureVideo(
view, view,
requireActivity(), requireActivity(),
ytdlpViewModel,
listOf(downloadItem), listOf(downloadItem),
embedSubsClicked = { embedSubsClicked = {
downloadItem.videoPreferences.embedSubs = it downloadItem.videoPreferences.embedSubs = it

@ -174,7 +174,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
audioFilenameTemplate?.summary = preferences.getString("file_name_template_audio", "%(uploader).30B - %(title).170B") audioFilenameTemplate?.summary = preferences.getString("file_name_template_audio", "%(uploader).30B - %(title).170B")
videoFilenameTemplate?.setOnPreferenceClickListener { 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() editor.putString("file_name_template", it).apply()
videoFilenameTemplate?.summary = it videoFilenameTemplate?.summary = it
} }

@ -17,6 +17,7 @@ import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
import android.os.Looper
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.text.format.DateFormat import android.text.format.DateFormat
@ -35,6 +36,7 @@ import android.widget.CheckBox
import android.widget.EditText import android.widget.EditText
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.ProgressBar
import android.widget.RadioButton import android.widget.RadioButton
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
@ -105,6 +107,7 @@ 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.logging.Handler
object UiUtil { object UiUtil {
@ -1302,6 +1305,7 @@ object UiUtil {
fun configureVideo( fun configureVideo(
view: View, view: View,
context: Activity, context: Activity,
ytdlpViewModel: YTDLPViewModel,
items: List<DownloadItem>, items: List<DownloadItem>,
embedSubsClicked : (Boolean) -> Unit, embedSubsClicked : (Boolean) -> Unit,
addChaptersClicked: (Boolean) -> Unit, addChaptersClicked: (Boolean) -> Unit,
@ -1764,7 +1768,8 @@ object UiUtil {
}else { }else {
"" ""
} }
showFilenameTemplateDialog(context, currentFilename) { val itemContext = if (items.size == 1) items.first() else null
showFilenameTemplateDialog(context, currentFilename, ytdlpViewModel = ytdlpViewModel, itemContext = itemContext) {
filenameTemplateSet(it) filenameTemplateSet(it)
} }
} }
@ -1791,6 +1796,7 @@ object UiUtil {
fun configureAudio( fun configureAudio(
view: View, view: View,
context: Activity, context: Activity,
ytdlpViewModel: YTDLPViewModel,
items: List<DownloadItem>, items: List<DownloadItem>,
embedThumbClicked: (Boolean) -> Unit, embedThumbClicked: (Boolean) -> Unit,
cropThumbClicked: (Boolean) -> Unit, cropThumbClicked: (Boolean) -> Unit,
@ -1867,7 +1873,8 @@ object UiUtil {
}else { }else {
"" ""
} }
showFilenameTemplateDialog(context, currentFilename) { val itemContext = if (items.size == 1) items.first() else null
showFilenameTemplateDialog(context, currentFilename, ytdlpViewModel = ytdlpViewModel, itemContext = itemContext) {
filenameTemplateSet(it) filenameTemplateSet(it)
} }
} }
@ -2103,7 +2110,7 @@ object UiUtil {
} }
@SuppressLint("RestrictedApi") @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) val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(dialogTitle) builder.setTitle(dialogTitle)
val view = context.layoutInflater.inflate(R.layout.filename_template_dialog, null) val view = context.layoutInflater.inflate(R.layout.filename_template_dialog, null)
@ -2174,6 +2181,42 @@ object UiUtil {
myTemplatesView.isVisible = true 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 { CoroutineScope(Dispatchers.IO).launch {
//handle personal template chips //handle personal template chips
val mychips = mutableListOf<Chip>() val mychips = mutableListOf<Chip>()
@ -2220,7 +2263,6 @@ object UiUtil {
chips.add(tmp) chips.add(tmp)
} }
withContext(Dispatchers.Main){ withContext(Dispatchers.Main){
if (mychips.isNotEmpty()){ if (mychips.isNotEmpty()){
myTemplatesView.isVisible = true myTemplatesView.isVisible = true

@ -41,6 +41,8 @@ import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.io.File import java.io.File
import java.lang.reflect.Type import java.lang.reflect.Type
import java.security.MessageDigest
import java.util.Base64
import java.util.Locale import java.util.Locale
import java.util.StringJoiner import java.util.StringJoiner
import java.util.UUID import java.util.UUID
@ -118,6 +120,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
}else{ }else{
request = YoutubeDLRequest(query) request = YoutubeDLRequest(query)
} }
request.addWriteInfoJson(query)
}else{ }else{
request = YoutubeDLRequest(emptyList()) request = YoutubeDLRequest(emptyList())
when (searchEngine){ when (searchEngine){
@ -374,6 +377,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
return parseYTDLPListResults(results) return parseYTDLPListResults(results)
} }
suspend fun getFormatsForAll(urls: List<String>, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result<MutableList<MutableList<Format>>> { suspend fun getFormatsForAll(urls: List<String>, progress: (progress: ResultViewModel.MultipleFormatProgress) -> Unit) : Result<MutableList<MutableList<Format>>> {
val formatCollection = mutableListOf<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) return Result.success(formatCollection)
} }
fun getFormats(url: String) : List<Format> { fun getFormats(url: String) : List<Format> {
val request = YoutubeDLRequest(url) val request = YoutubeDLRequest(url)
request.addOption("--print", "%(formats)s") request.addOption("--print", "%(formats)s")
@ -583,7 +586,51 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
return Result.failure(e) 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 { fun parseYTDLRequestString(request : YoutubeDLRequest) : String {
val arr = request.buildCommand().toMutableList() 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?) { private fun YoutubeDLRequest.setYoutubeExtractorArgs(url: String?) {
val extractorArgs = mutableListOf<String>() val extractorArgs = mutableListOf<String>()
@ -858,11 +896,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
request.addOption("--proxy", proxy) 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) val keepCache = sharedPreferences.getBoolean("keep_cache", false)
if(keepCache){ if(keepCache){
request.addOption("--keep-fragments") 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 noCache = writtenPath || (!sharedPreferences.getBoolean("cache_downloads", true) && File(FileUtil.formatPath(downloadItem.downloadPath)).canWrite())
val request = ytdlpUtil.buildYoutubeDLRequest(downloadItem) 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() downloadItem.status = DownloadRepository.Status.Active.toString()
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
delay(1500) delay(1500)
@ -375,7 +381,6 @@ class DownloadWorker(
FileUtil.deleteFile("${cachePath}/${infoJsonName}.info.json") FileUtil.deleteFile("${cachePath}/${infoJsonName}.info.json")
} }
if (logDownloads){ if (logDownloads){
logRepo.update(it.message ?: "", logItem.id) logRepo.update(it.message ?: "", logItem.id)
}else{ }else{

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp" android:padding="10dp"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -31,6 +31,46 @@
</com.google.android.material.textfield.TextInputLayout> </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 <LinearLayout
android:id="@+id/mytemplates" android:id="@+id/mytemplates"
android:visibility="gone" 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="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">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="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> </resources>

Loading…
Cancel
Save