other fixes

pull/1112/head
deniscerri 5 months ago
parent 1a60bf9e53
commit c62332ced8
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -40,9 +40,6 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a
private var formatUtil = FormatUtil(application)
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)
val genericAudioFormats = formatUtil.getGenericAudioFormats(application.resources)
val genericVideoFormats = formatUtil.getGenericVideoFormats(application.resources)
var sortBy = FormatSorting.valueOf(sharedPreferences.getString("format_order", "filesize")!!)
var filterBy = MutableStateFlow(FormatCategory.valueOf(sharedPreferences.getString("format_filter", "ALL")!!))
@ -175,9 +172,9 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a
if (finalFormats.isEmpty()) {
finalFormats = if (items.first().type == DownloadType.audio){
genericAudioFormats
formatUtil.getGenericAudioFormats(application.resources)
}else{
genericVideoFormats
formatUtil.getGenericVideoFormats(application.resources)
}
}
@ -218,6 +215,10 @@ class FormatViewModel(private val application: Application) : AndroidViewModel(a
fun getFormatsForItemsBasedOnFormat(item: Format?, audioFormats: List<Format>? = null) : MutableList<MultipleItemFormatTuple> {
val formatsToReturn = mutableListOf<MultipleItemFormatTuple>()
val genericAudioFormats = formatUtil.getGenericAudioFormats(application.resources)
val genericVideoFormats = formatUtil.getGenericVideoFormats(application.resources)
val f = if (genericAudioFormats.contains(item) || genericVideoFormats.contains(item)) item else null
selectedItems.value.forEach {

@ -24,6 +24,7 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.core.os.bundleOf
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
@ -700,6 +701,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
if(checked) {
it.container = "mp4"
}
it.format = downloadViewModel.getFormat(it.allFormats,DownloadType.video)
}
CoroutineScope(Dispatchers.IO).launch { items.forEach { downloadViewModel.updateDownload(it) } }
},

@ -17,6 +17,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.edit
import androidx.core.view.isVisible
import androidx.core.view.setPadding
import androidx.fragment.app.Fragment

@ -8,33 +8,25 @@ import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import android.widget.ScrollView
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.edit
import androidx.core.view.ScrollingView
import androidx.core.view.children
import androidx.core.view.get
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdl.MainActivity
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.viewmodel.LogViewModel
import com.deniscerri.ytdl.ui.adapter.LogAdapter
import com.deniscerri.ytdl.util.Extensions.enableFastScroll
import com.deniscerri.ytdl.util.Extensions.enableTextHighlight
import com.deniscerri.ytdl.util.Extensions.setCustomTextSize
@ -56,17 +48,14 @@ import org.greenrobot.eventbus.ThreadMode
class DownloadLogFragment : Fragment() {
private lateinit var logRecyclerView: RecyclerView
private lateinit var horizontalScrollingView: HorizontalScrollView
private lateinit var logAdapter: LogAdapter
private lateinit var content: TextView
private lateinit var contentScrollView : ScrollView
private lateinit var topAppBar: MaterialToolbar
private lateinit var copyLog : ExtendedFloatingActionButton
private lateinit var mainActivity: MainActivity
private lateinit var logViewModel: LogViewModel
private lateinit var sharedPreferences: SharedPreferences
private var logID: Long? = null
private var contentText: String = ""
private var contentLineCount: Int = 0
private var autoScroll : Boolean = true
private var scrollDownBtn : MenuItem? = null
@ -92,29 +81,23 @@ class DownloadLogFragment : Fragment() {
mainActivity.onBackPressedDispatcher.onBackPressed()
}
logRecyclerView = view.findViewById(R.id.log_recycler_view)
logAdapter = LogAdapter()
logRecyclerView.layoutManager = LinearLayoutManager(requireContext())
logRecyclerView.adapter = logAdapter
logRecyclerView.itemAnimator = null
logAdapter.isWrapped = sharedPreferences.getBoolean("wrap_text_log", false)
logAdapter.textSize = sharedPreferences.getFloat("log_zoom", 2f) + 13f
logAdapter.highlight = sharedPreferences.getBoolean("use_code_color_highlighter", true)
horizontalScrollingView = view.findViewById(R.id.horizontal_container)
content = view.findViewById(R.id.content)
content.setTextIsSelectable(true)
content.layoutParams!!.width = ActionBar.LayoutParams.WRAP_CONTENT
contentScrollView = view.findViewById(R.id.content_scrollview)
val bottomAppBar = view.findViewById<BottomAppBar>(R.id.bottomAppBar)
topAppBar.setOnClickListener {
logRecyclerView.scrollTo(0,0)
contentScrollView.scrollTo(0,0)
bottomAppBar?.menu?.get(1)?.isVisible = true
}
copyLog = view.findViewById(R.id.copy_log)
copyLog.setOnClickListener {
val clipboard: ClipboardManager =
mainActivity.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setText(contentText)
clipboard.setText(content.text)
Snackbar.make(bottomAppBar, getString(R.string.copied_to_clipboard), Snackbar.LENGTH_LONG)
.setAnchorView(bottomAppBar)
.show()
@ -142,23 +125,49 @@ class DownloadLogFragment : Fragment() {
}
}
//logRecyclerView.enableFastScroll()
contentScrollView.enableFastScroll()
scrollDownBtn = bottomAppBar?.menu?.children?.first { it.itemId == R.id.scroll_down }
val slider = view.findViewById<Slider>(R.id.textsize_seekbar)
bottomAppBar?.setOnMenuItemClickListener { m: MenuItem ->
when(m.itemId){
R.id.wrap -> {
val newState = !logAdapter.isWrapped
logAdapter.isWrapped = newState
sharedPreferences.edit(commit = true) { putBoolean("wrap_text_log", newState) }
logAdapter.notifyDataSetChanged()
var scrollView = requireView().findViewById<HorizontalScrollView>(R.id.horizontalscroll_output)
if(scrollView != null){
val parent = (scrollView.parent as ViewGroup)
scrollView.removeAllViews()
parent.removeView(scrollView)
parent.addView(content, 0)
// contentScrollView.setPadding(0,0,0,
// (requireContext().resources.displayMetrics.density * 150).toInt()
// )
sharedPreferences.edit().putBoolean("wrap_text_log", true).apply()
updateAutoScrollState()
}else{
val parent = content.parent as ViewGroup
parent.removeView(content)
scrollView = HorizontalScrollView(requireContext())
// scrollView.setPadding(0,0,0,
// (requireContext().resources.displayMetrics.density * 150).toInt()
// )
contentScrollView.setPadding(0,0,0,0)
scrollView.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
scrollView.addView(content)
scrollView.id = R.id.horizontalscroll_output
parent.addView(scrollView, 0)
updateAutoScrollState()
sharedPreferences.edit().putBoolean("wrap_text_log", false).apply()
}
}
R.id.scroll_down -> {
m.isVisible = false
autoScroll = true
logRecyclerView.smoothScrollToPosition(contentLineCount)
contentScrollView.fullScroll(View.FOCUS_DOWN)
}
R.id.text_size -> {
@ -189,80 +198,42 @@ class DownloadLogFragment : Fragment() {
this.valueFrom = 0f
this.valueTo = 10f
this.value = sharedPreferences.getFloat("log_zoom", 2f)
logAdapter.textSize = this.value + 13f
logAdapter.notifyDataSetChanged()
content.setCustomTextSize(this.value + 13f)
this.addOnChangeListener { slider, value, fromUser ->
logAdapter.textSize = value + 13f
logAdapter.notifyDataSetChanged()
content.setCustomTextSize(value + 13f)
sharedPreferences.edit(true){
putFloat("log_zoom", value)
}
}
}
logRecyclerView.setOnScrollChangeListener { view, sx, sy, osx, osy ->
contentScrollView.setOnScrollChangeListener { view, sx, sy, osx, osy ->
updateAutoScrollState()
}
logRecyclerView.setOnTouchListener { view, motionEvent ->
contentScrollView.setOnTouchListener { view, motionEvent ->
autoScroll = false
false
}
logRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
private var startX = 0f
private var startY = 0f
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
when (e.action) {
MotionEvent.ACTION_DOWN -> {
startX = e.x
startY = e.y
// Prevent parent from stealing the initial touch
rv.parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE -> {
val dx = Math.abs(e.x - startX)
val dy = Math.abs(e.y - startY)
// If moving more vertically than horizontally, lock vertical scroll
if (dy > dx) {
rv.parent.requestDisallowInterceptTouchEvent(true)
} else if (dx > dy && !logAdapter.isWrapped) {
// If moving horizontally and wrap is OFF, let the parent take it
rv.parent.requestDisallowInterceptTouchEvent(false)
}
}
}
return false
sharedPreferences.getBoolean("wrap_text_log", false).apply {
if (this){
bottomAppBar.menu.performIdentifierAction(R.id.wrap, 0)
}
override fun onTouchEvent(
rv: RecyclerView,
e: MotionEvent
) {
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
})
}
logViewModel.getLogFlowByID(logID!!).observe(viewLifecycleOwner){logItem ->
kotlin.runCatching {
requireActivity().runOnUiThread{
if (logItem != null){
if (logItem.content.isNotBlank()) {
contentText = logItem.content
val lines = contentText.split("\n")
contentLineCount = lines.size
logAdapter.submitList(lines)
bottomAppBar?.menu?.get(1)?.isVisible = logRecyclerView.canScrollVertically(1)
content.setText(logItem.content, TextView.BufferType.SPANNABLE)
bottomAppBar?.menu?.get(1)?.isVisible = contentScrollView.canScrollVertically(1)
}
if (autoScroll && contentLineCount > 0){
logRecyclerView.post {
logRecyclerView.smoothScrollToPosition(contentLineCount)
if (autoScroll){
//content.scrollTo(0, content.height)
content.post {
contentScrollView.fullScroll(View.FOCUS_DOWN)
}
}
}
@ -272,7 +243,7 @@ class DownloadLogFragment : Fragment() {
}
private fun updateAutoScrollState() {
val canVerticallyScroll = logRecyclerView.canScrollVertically(1)
val canVerticallyScroll = contentScrollView.canScrollVertically(1)
scrollDownBtn?.isVisible = canVerticallyScroll
}

@ -12,7 +12,6 @@ import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
@ -31,15 +30,12 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.deniscerri.ytdl.R
import com.deniscerri.ytdl.database.models.TerminalItem
import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
import com.deniscerri.ytdl.database.viewmodel.TerminalViewModel
import com.deniscerri.ytdl.ui.adapter.LogAdapter
import com.deniscerri.ytdl.util.Extensions.enableTextHighlight
import com.deniscerri.ytdl.util.Extensions.setCustomTextSize
import com.deniscerri.ytdl.util.FileUtil
@ -61,11 +57,10 @@ class TerminalFragment : Fragment() {
private lateinit var topAppBar: MaterialToolbar
private lateinit var notificationUtil: NotificationUtil
private lateinit var terminalViewModel: TerminalViewModel
private lateinit var logRecyclerView: RecyclerView
private lateinit var horizontalScrollingView: HorizontalScrollView
private lateinit var logAdapter: LogAdapter
private lateinit var output: TextView
private lateinit var input: EditText
private lateinit var fab: ExtendedFloatingActionButton
private lateinit var scrollView: ScrollView
private lateinit var bottomAppBar: BottomAppBar
private lateinit var commandTemplateViewModel: CommandTemplateViewModel
private lateinit var sharedPreferences: SharedPreferences
@ -73,9 +68,6 @@ class TerminalFragment : Fragment() {
private lateinit var imm : InputMethodManager
private lateinit var metrics: DisplayMetrics
private var contentText: String = ""
private var contentLineCount: Int = 0
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -90,7 +82,7 @@ class TerminalFragment : Fragment() {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("input", input.text.toString())
outState.putString("output", contentText)
outState.putString("output", output.text.toString())
outState.putBoolean("run", fab.text == requireActivity().getString(R.string.run_command))
outState.putLong("downloadID", downloadID)
}
@ -104,24 +96,10 @@ class TerminalFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
var bundle = savedInstanceState
imm = requireActivity().getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
logRecyclerView = view.findViewById(R.id.log_recycler_view)
logAdapter = LogAdapter()
logRecyclerView.layoutManager = LinearLayoutManager(requireContext())
logRecyclerView.adapter = logAdapter
logRecyclerView.itemAnimator = null
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
logAdapter.isWrapped = sharedPreferences.getBoolean("wrap_text_terminal", false)
logAdapter.textSize = sharedPreferences.getFloat("terminal_zoom", 2f) + 13f
logAdapter.highlight = sharedPreferences.getBoolean("use_code_color_highlighter", true)
horizontalScrollingView = view.findViewById(R.id.horizontal_container)
scrollView = view.findViewById(R.id.custom_command_scrollview)
topAppBar = requireActivity().findViewById(R.id.custom_command_toolbar)
topAppBar.setNavigationOnClickListener { requireActivity().finish() }
topAppBar.setOnClickListener { logRecyclerView.scrollTo(0,0) }
topAppBar.setOnClickListener { scrollView.scrollTo(0,0) }
input = view.findViewById(R.id.command_edittext)
fab = view.findViewById(R.id.command_fab)
@ -142,6 +120,7 @@ class TerminalFragment : Fragment() {
}
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
metrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(metrics)
@ -224,18 +203,21 @@ class TerminalFragment : Fragment() {
true
}
output = view.findViewById(R.id.custom_command_output)
output.setTextIsSelectable(true)
output.layoutParams!!.width = LayoutParams.WRAP_CONTENT
input.requestFocus()
fab.setOnClickListener {
if (fab.text == requireActivity().getString(R.string.run_command)){
input.visibility = View.GONE
val commandLine = "~ $ ${input.text}"
val txt = "${output.text}\n~ $ ${input.text}\n"
output.text = txt
showCancelFab()
imm.hideSoftInputFromWindow(input.windowToken, 0)
lifecycleScope.launch {
val command = input.text.toString().replaceFirst("yt-dlp", "")
downloadID = withContext(Dispatchers.IO){
terminalViewModel.insert(TerminalItem(command = command, log = commandLine))
terminalViewModel.insert(TerminalItem(command = command, log = output.text.toString()))
}
terminalViewModel.startTerminalDownloadWorker(TerminalItem(downloadID, command))
input.visibility = View.GONE
@ -259,55 +241,13 @@ class TerminalFragment : Fragment() {
input.append(bundle?.getString("input") ?: "")
input.requestFocus()
input.setSelection(input.text.length)
val list = (bundle?.getString("output")?.split("\r","\n") ?: contentText.split("\r","\n"))
contentLineCount = list.size
contentText = list.joinToString("\n")
logAdapter.submitList(list)
output.text = bundle?.getString("output") ?: output.text
output.isVisible = output.text.toString().isNotEmpty()
}
if (bundle?.getBoolean("run") == true){
showCancelFab()
}
logRecyclerView.addOnItemTouchListener(object : RecyclerView.OnItemTouchListener {
private var startX = 0f
private var startY = 0f
override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
when (e.action) {
MotionEvent.ACTION_DOWN -> {
startX = e.x
startY = e.y
// Prevent parent from stealing the initial touch
rv.parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE -> {
val dx = Math.abs(e.x - startX)
val dy = Math.abs(e.y - startY)
// If moving more vertically than horizontally, lock vertical scroll
if (dy > dx) {
rv.parent.requestDisallowInterceptTouchEvent(true)
} else if (dx > dy && !logAdapter.isWrapped) {
// If moving horizontally and wrap is OFF, let the parent take it
rv.parent.requestDisallowInterceptTouchEvent(false)
}
}
}
return false
}
override fun onTouchEvent(
rv: RecyclerView,
e: MotionEvent
) {
}
override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
}
})
runWorkerListener()
}
@ -321,15 +261,31 @@ class TerminalFragment : Fragment() {
topAppBar.setOnMenuItemClickListener { m: MenuItem ->
when(m.itemId){
R.id.wrap -> {
val newState = !logAdapter.isWrapped
logAdapter.isWrapped = newState
sharedPreferences.edit(commit = true) { putBoolean("wrap_text_terminal", newState) }
logAdapter.notifyDataSetChanged()
var scrollView = requireView().findViewById<HorizontalScrollView>(R.id.horizontalscroll_output)
if(scrollView != null){
val parent = (scrollView.parent as ViewGroup)
scrollView.removeAllViews()
parent.removeView(scrollView)
parent.addView(output, 0)
sharedPreferences.edit().putBoolean("wrap_text_terminal", true).apply()
}else{
val parent = output.parent as ViewGroup
parent.removeView(output)
scrollView = HorizontalScrollView(requireContext())
scrollView.layoutParams = LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
scrollView.addView(output)
scrollView.id = R.id.horizontalscroll_output
parent.addView(scrollView, 0)
sharedPreferences.edit().putBoolean("wrap_text_terminal", false).apply()
}
}
R.id.export_clipboard -> {
lifecycleScope.launch(Dispatchers.IO){
val clipboard: ClipboardManager = requireActivity().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setText(contentText)
clipboard.setText(output.text)
}
}
@ -344,20 +300,22 @@ class TerminalFragment : Fragment() {
this.valueFrom = 0f
this.valueTo = 10f
this.value = sharedPreferences.getFloat("terminal_zoom", 2f)
logAdapter.textSize = this.value + 13f
logAdapter.notifyDataSetChanged()
output.setCustomTextSize(this.value + 13f)
input.setCustomTextSize(this.value + 13f)
this.addOnChangeListener { slider, value, fromUser ->
logAdapter.textSize = value + 13f
logAdapter.notifyDataSetChanged()
output.setCustomTextSize(value + 13f)
input.setCustomTextSize(value + 13f)
sharedPreferences.edit(true){
putFloat("terminal_zoom", value)
}
}
}
sharedPreferences.getBoolean("wrap_text_terminal", false).apply {
if (this){
bottomAppBar.menu.performIdentifierAction(R.id.wrap, 0)
}
}
}
private fun hideCancelFab() {
kotlin.runCatching {
@ -394,13 +352,11 @@ class TerminalFragment : Fragment() {
requireActivity().runOnUiThread{
if (it != null){
if (!it.log.isNullOrBlank()) {
contentText = it.log!!
val lines = contentText.split("\r","\n")
contentLineCount = lines.size
logAdapter.submitList(lines) {
logRecyclerView.scrollToPosition(lines.size - 1)
}
output.isVisible = true
output.text = it.log
}
output.scrollTo(0, output.height)
scrollView.fullScroll(View.FOCUS_DOWN)
input.visibility = View.GONE
showCancelFab()
}

@ -316,15 +316,19 @@ object FileUtil {
if (preference.isNullOrBlank()) {
val externalPath = context.getExternalFilesDir(null)
return if (externalPath == null){
context.cacheDir.absolutePath + "/downloads/"
context.cacheDir.absolutePath + "/ytdlnis_cache/"
}else{
externalPath.absolutePath + "/downloads/"
externalPath.absolutePath + "/ytdlnis_cache/"
}
}else {
return formatPath(preference)
}
}
fun getCacheDownloadsPath(context: Context): String {
return "${getCachePath(context)}dl"
}
fun getInfoJsonPath(context: Context) : String {
return "${getCachePath(context)}infojsons"
}

@ -661,7 +661,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
try {
val response = RuntimeManager.getInstance().execute(request)
return response.out.replace(FileUtil.getCachePath(context) + "${item.id}/", "").trim()
return response.out.replace(FileUtil.getCacheDownloadsPath(context) + "/${item.id}/", "").trim()
} catch (ex: Exception) {
return ex.message ?: ""
}
@ -857,6 +857,14 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
metadataCommands.addOption("--parse-metadata", " ${downloadItem.playlistIndex}: %(playlist_index)s")
}
if (downloadItem.playlistTitle.isNotBlank() && useItemURL) {
metadataCommands.addOption("--replace-in-metadata", "playlist,playlist_title", "^.*$", downloadItem.playlistTitle)
}
if (downloadItem.playlistIndex != null) {
metadataCommands.addOption("--parse-metadata", "%(playlist_autonumber)s:playlist_autonumber")
}
downloadItem.rowNumber.apply {
if (this > 0) {
request.addOption("--autonumber-start", this.toString())
@ -875,7 +883,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
request.addOption("--no-simulate")
request.addOption("--print", "after_move:'%(filepath,_filename)s'")
}else{
val cacheDir = FileUtil.getCachePath(context)
val cacheDir = FileUtil.getCacheDownloadsPath(context)
downDir = File(cacheDir, downloadItem.id.toString())
downDir.delete()
downDir.mkdirs()
@ -1263,11 +1271,15 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
altAudioF = this.format_id.split("-")[0]
this.format_id
}
} else this.format_id
} ?: f
} else {
this.format_id
}
} ?: if (f == "wa") "" else f
}.ifBlank { "ba" }
val preferredAudioLanguage = sharedPreferences.getString("audio_language", "")!!
val preferDRCAudio = sharedPreferences.getBoolean("prefer_drc_audio", false)
val usingWorstAudio = downloadItem.videoPreferences.audioFormatIDs.any { it == "wa" }
if (downloadItem.videoPreferences.removeAudio) audioF = ""
var abrSort = ""
@ -1337,7 +1349,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
val list = mutableListOf<String>()
if (preferredAudioLanguage.isNotEmpty() && !downloadItem.videoPreferences.removeAudio) list.add("ba[language^=$preferredAudioLanguage]")
if (preferDRCAudio) list.add("ba[format_id$=-drc]")
list.add(audioF)
list
}.apply {
@ -1345,6 +1356,11 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
if (!preferredAudioFormatIDs.contains(audioF) && audioF != "ba"){
preferredAudioFormatIDs.add(0, audioF)
}
if (preferredAudioFormatIDs.contains("wa")) {
preferredFormatIDs.remove("wa")
}
// ^ [audioF, preferredAID1, preferredAID2, ....]
if (preferredAudioFormatIDs.any{it.contains("+")}){
request.addOption("--audio-multistreams")
@ -1426,6 +1442,8 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
if (abrSort.isNotBlank()) {
formatSorting.add("abr:${abrSort}")
} else if (usingWorstAudio) {
formatSorting.add("+abr")
}
// if (preferredLanguage.isNotBlank()) {
@ -1516,7 +1534,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
if (sponsorBlockURL.isNotBlank()) request.addOption("--sponsorblock-api", sponsorBlockURL)
}
val cache = File(FileUtil.getCachePath(context))
val cache = File(FileUtil.getCacheDownloadsPath(context))
cache.mkdirs()
val conf = File(cache.absolutePath + "/${System.currentTimeMillis()}${UUID.randomUUID()}.txt")
conf.createNewFile()

@ -36,7 +36,7 @@ class CleanUpLeftoverDownloads(
val activeDownloadCount = downloadRepo.getActiveDownloadsCount()
if (activeDownloadCount == 0){
File(FileUtil.getCachePath(context)).deleteRecursively()
File(FileUtil.getCacheDownloadsPath(context)).deleteRecursively()
}
return Result.success()

@ -188,7 +188,7 @@ class DownloadWorker(
}
}
val cacheDir = FileUtil.getCachePath(context)
val cacheDir = FileUtil.getCacheDownloadsPath(context)
val tempFileDir = File(cacheDir, downloadItem.id.toString())
tempFileDir.delete()
tempFileDir.mkdirs()

@ -30,12 +30,13 @@ class MoveCacheFilesWorker(
val notificationUtil = NotificationUtil(App.instance)
val id = System.currentTimeMillis().toInt()
val cachePath = FileUtil.getCachePath(context)
val cachePath = FileUtil.getCacheDownloadsPath(context)
val downloadFolders = File(cachePath)
val allContent = downloadFolders.walk()
val totalFiles = allContent.count()
val destination = File(FileUtil.getDefaultApplicationPath(), "CACHE_IMPORT")
destination.mkdirs()
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
@ -65,6 +66,11 @@ class MoveCacheFilesWorker(
it.renameTo(destFile)
}
}
downloadFolders.listFiles()?.forEach { child ->
child.deleteRecursively()
}
val handler = Handler(Looper.getMainLooper())
handler.post {
Toast.makeText(context, context.getString(R.string.ok), Toast.LENGTH_SHORT).show()

@ -35,25 +35,52 @@
</com.google.android.material.appbar.AppBarLayout>
<HorizontalScrollView
android:id="@+id/horizontal_container"
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:fillViewport="true"
android:scrollbars="horizontal"
app:layout_constraintBottom_toTopOf="@+id/coordinatorLayout3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appbarlayout">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/log_recycler_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="100dp" />
<me.zhanghai.android.fastscroll.FastScrollScrollView
android:id="@+id/content_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="wrap_content"
android:id="@+id/horizontalscroll_output"
android:layout_height="wrap_content">
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:gravity="bottom"
android:padding="10dp"
android:scrollbars="none"
android:textIsSelectable="true"
android:textSize="15sp" />
</HorizontalScrollView>
</LinearLayout>
</me.zhanghai.android.fastscroll.FastScrollScrollView>
</HorizontalScrollView>
</FrameLayout>
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress"

@ -6,13 +6,15 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.core.widget.NestedScrollView
android:id="@+id/terminal_scroll_view"
android:layout_width="match_parent"
<ScrollView
android:id="@+id/custom_command_scrollview"
android:layout_width="0dp"
android:layout_height="0dp"
android:fillViewport="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/coordinatorLayout">
android:layout_margin="10dp"
app:layout_constraintBottom_toTopOf="@+id/coordinatorLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
@ -21,39 +23,39 @@
android:orientation="vertical">
<HorizontalScrollView
android:id="@+id/horizontal_container"
android:id="@+id/horizontalscroll_output"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="horizontal"
app:layout_constraintBottom_toTopOf="@+id/coordinatorLayout3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appbarlayout">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/log_recycler_view"
android:layout_height="match_parent">
<TextView
android:id="@+id/custom_command_output"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:clipToPadding="false"/>
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:gravity="bottom"
android:scrollbars="horizontal|vertical"
android:scrollHorizontally="true"
android:textIsSelectable="true"
android:textSize="15sp" />
</HorizontalScrollView>
<EditText
android:id="@+id/command_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:fontFamily="monospace"
android:paddingHorizontal="10dp"
android:gravity="start"
android:inputType="textMultiLine|textNoSuggestions"
android:maxLines="10000"
android:text="yt-dlp "
android:paddingBottom="100dp"
android:textSize="15sp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</ScrollView>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinatorLayout"

@ -169,7 +169,7 @@
<string name="download_rescheduled_to">Download rescheduled to:</string>
<string name="file_size">File size</string>
<string name="clear_temporary_files">Clear temporary files</string>
<string name="clear_temporary_files_summary">Delete cached files from crashed/errored/cancelled downloads</string>
<string name="clear_temporary_files_summary">Delete cached files, infojsons and other temporary configurations</string>
<string name="cache_cleared">Temporary files cleared</string>
<string name="downloads_running_try_later">Download worker is running. Try again later</string>
<string name="ytdl_version">yt-dlp version</string>
@ -272,7 +272,7 @@
<string name="crop_thumb_summary">Crop the thumbnail into a square for audio downloads</string>
<string name="audio_only_item">This item only contains audio formats</string>
<string name="move_temporary_files">Move temporary files</string>
<string name="move_temporary_files_summary">Transfer cached files to the downloads folder</string>
<string name="move_temporary_files_summary">Transfer cached download files to the downloads folder</string>
<string name="custom_audio_quality">Use custom audio quality</string>
<string name="retries">Retries</string>
<string name="fragment_retries">Fragment retries</string>

Loading…
Cancel
Save