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 {
|
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…
Reference in a new issue