added restrict filenames preference and changed download card design

This commit is contained in:
deniscerri 2023-03-19 16:25:37 +01:00
parent cb6fd86239
commit d3887dd7d9
No known key found for this signature in database
GPG key ID: 95C43D517D830350
25 changed files with 399 additions and 242 deletions

View file

@ -320,7 +320,7 @@
<PersistentState> <PersistentState>
<option name="values"> <option name="values">
<map> <map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/folder_delete/baseline_folder_delete_24.xml" /> <entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/drive_file_rename_outline/baseline_drive_file_rename_outline_24.xml" />
</map> </map>
</option> </option>
</PersistentState> </PersistentState>
@ -330,7 +330,7 @@
</option> </option>
<option name="values"> <option name="values">
<map> <map>
<entry key="outputName" value="ic_folder_delete" /> <entry key="outputName" value="if_file_rename" />
<entry key="sourceFile" value="C:\Users\denis\Desktop\FREKUENCA\icons8-google-translate.svg" /> <entry key="sourceFile" value="C:\Users\denis\Desktop\FREKUENCA\icons8-google-translate.svg" />
</map> </map>
</option> </option>

View file

@ -101,10 +101,10 @@
android:configChanges="layoutDirection|locale" android:configChanges="layoutDirection|locale"
android:theme="@style/AppDefaultTheme" android:theme="@style/AppDefaultTheme"
android:parentActivityName=".MainActivity" android:parentActivityName=".MainActivity"
android:label="@string/run_command" android:label="@string/terminal"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="ytdlnis.CustomCommandActivity" /> <action android:name="ytdlnis.TerminalActivity" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>

View file

@ -1,12 +1,12 @@
package com.deniscerri.ytdlnis.adapter package com.deniscerri.ytdlnis.adapter
import android.app.Activity import android.app.Activity
import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -26,16 +26,16 @@ import java.util.*
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) { class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
private val onItemClickListener: OnItemClickListener private val onItemClickListener: OnItemClickListener
private val activity: Activity private val activity: Activity
private val fileUtil: FileUtil private var fileUtil: FileUtil
init { init {
this.onItemClickListener = onItemClickListener this.onItemClickListener = onItemClickListener
this.activity = activity this.activity = activity
this.fileUtil = FileUtil() fileUtil = FileUtil()
} }
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) { class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
val cardView: MaterialCardView val cardView: FrameLayout
init { init {
cardView = itemView.findViewById(R.id.download_card_view) cardView = itemView.findViewById(R.id.download_card_view)
@ -54,16 +54,16 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
// THUMBNAIL ---------------------------------- // THUMBNAIL ----------------------------------
val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view) val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
val imageURL = item!!.thumb val imageURL = item!!.thumb
val uiHandler = Handler(Looper.getMainLooper())
if (imageURL.isNotEmpty()) { if (imageURL.isNotEmpty()) {
val uiHandler = Handler(Looper.getMainLooper())
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) } uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
} else { } else {
val uiHandler = Handler(Looper.getMainLooper())
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) } uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
} }
val duration = card.findViewById<TextView>(R.id.duration)
duration.text = item.duration
// TITLE ---------------------------------- // TITLE ----------------------------------
val itemTitle = card.findViewById<TextView>(R.id.title) val itemTitle = card.findViewById<TextView>(R.id.title)
var title = item.title var title = item.title
@ -72,10 +72,6 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
} }
itemTitle.text = title itemTitle.text = title
// Author ----------------------------------
val author = card.findViewById<TextView>(R.id.subtitle)
author.text = item.author
// Format Note ---------------------------------- // Format Note ----------------------------------
val formatNote = card.findViewById<TextView>(R.id.format_note) val formatNote = card.findViewById<TextView>(R.id.format_note)
if (item.format.format_note.isNotEmpty()){ if (item.format.format_note.isNotEmpty()){
@ -111,16 +107,17 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
// Type Icon Button // Type Icon Button
val btn = card.findViewById<MaterialButton>(R.id.action_button) val btn = card.findViewById<MaterialButton>(R.id.action_button)
if (btn.hasOnClickListeners()) btn.setOnClickListener(null)
when(item.type) { when(item.type) {
DownloadViewModel.Type.audio -> { DownloadViewModel.Type.audio -> {
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music) btn.setIconResource(R.drawable.ic_music)
} }
DownloadViewModel.Type.video -> { DownloadViewModel.Type.video -> {
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video) btn.setIconResource(R.drawable.ic_video)
} }
else -> { else -> {
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_terminal) btn.setIconResource(R.drawable.ic_terminal)
} }
} }

View file

@ -7,6 +7,7 @@ import android.os.Looper
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncDifferConfig
@ -35,7 +36,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
} }
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) { class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
val cardView: MaterialCardView val cardView: FrameLayout
init { init {
cardView = itemView.findViewById(R.id.download_card_view) cardView = itemView.findViewById(R.id.download_card_view)
} }
@ -60,25 +61,24 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
} else { } else {
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) } uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
} }
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0))
val duration = card.findViewById<TextView>(R.id.duration)
duration.text = item.duration
// TITLE ---------------------------------- // TITLE ----------------------------------
val itemTitle = card.findViewById<TextView>(R.id.title) val itemTitle = card.findViewById<TextView>(R.id.title)
var title = item!!.title var title = item.title
if (title.length > 100) { if (title.length > 100) {
title = title.substring(0, 40) + "..." title = title.substring(0, 40) + "..."
} }
itemTitle.text = title itemTitle.text = title
val itemUrl = card.findViewById<TextView>(R.id.subtitle) val formatNote = card.findViewById<TextView>(R.id.format_note)
itemUrl.text = item.url
val formatNote = card.findViewById<Chip>(R.id.format_note)
if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility = if (item.format.format_note == "?" || item.format.format_note == "") formatNote!!.visibility =
View.GONE View.GONE
else formatNote!!.text = item.format.format_note.uppercase() else formatNote!!.text = item.format.format_note.uppercase()
val codec = card.findViewById<Chip>(R.id.codec) val codec = card.findViewById<TextView>(R.id.codec)
val codecText = val codecText =
if (item.format.encoding != "") { if (item.format.encoding != "") {
item.format.encoding.uppercase() item.format.encoding.uppercase()
@ -94,7 +94,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
codec.text = codecText codec.text = codecText
} }
val fileSize = card.findViewById<Chip>(R.id.file_size) val fileSize = card.findViewById<TextView>(R.id.file_size)
val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize) val fileSizeReadable = fileUtil.convertFileSize(item.format.filesize)
if (fileSizeReadable == "?") fileSize.visibility = View.GONE if (fileSizeReadable == "?") fileSize.visibility = View.GONE
else fileSize.text = fileSizeReadable else fileSize.text = fileSizeReadable

View file

@ -69,6 +69,10 @@ class PlaylistAdapter(onItemClickListener: OnItemClickListener, activity: Activi
} }
itemTitle.text = title itemTitle.text = title
val duration = card.findViewById<TextView>(R.id.duration)
duration.text = item.duration
// CHECKBOX ---------------------------------- // CHECKBOX ----------------------------------
val check = card.findViewById<CheckBox>(R.id.checkBox) val check = card.findViewById<CheckBox>(R.id.checkBox)
check.isChecked = checkedItems.contains(item.url) check.isChecked = checkedItems.contains(item.url)

View file

@ -37,6 +37,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
private var bestVideoFormat : Format private var bestVideoFormat : Format
private var bestAudioFormat : Format private var bestAudioFormat : Format
private var defaultVideoFormats : MutableList<Format>
enum class Type { enum class Type {
audio, video, command audio, video, command
} }
@ -57,15 +58,22 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
val videoFormat = getApplication<App>().resources.getStringArray(R.array.video_formats) val videoFormat = getApplication<App>().resources.getStringArray(R.array.video_formats)
val videoContainer = sharedPreferences.getString("video_format", getApplication<App>().resources.getString(R.string.defaultValue)) val videoContainer = sharedPreferences.getString("video_format", getApplication<App>().resources.getString(R.string.defaultValue))
bestVideoFormat = Format(
videoFormat[videoFormat.lastIndex], defaultVideoFormats = mutableListOf()
videoContainer!!, videoFormat.forEach {
"", val tmp = Format(
"", it,
"", videoContainer!!,
0, "",
videoFormat[videoFormat.lastIndex] "",
) "",
0,
it
)
defaultVideoFormats.add(tmp)
}
bestVideoFormat = defaultVideoFormats.last()
val audioContainer = sharedPreferences.getString("audio_format", "mp3") val audioContainer = sharedPreferences.getString("audio_format", "mp3")
bestAudioFormat = Format( bestAudioFormat = Format(
@ -172,17 +180,19 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
} }
Type.video -> { Type.video -> {
return try { return try {
val theFormats = formats.ifEmpty { defaultVideoFormats }
val qualityPreference = sharedPreferences.getString("video_quality", getApplication<App>().resources.getString(R.string.best_quality)) val qualityPreference = sharedPreferences.getString("video_quality", getApplication<App>().resources.getString(R.string.best_quality))
if (qualityPreference == getApplication<App>().resources.getString(R.string.worst_quality)){ if (qualityPreference == getApplication<App>().resources.getString(R.string.worst_quality)){
formats.first { !it.format_note.contains("audio", ignoreCase = true) } theFormats.first { !it.format_note.contains("audio", ignoreCase = true) }
} }
if (qualityPreference == getApplication<App>().resources.getString(R.string.best_quality)){ if (qualityPreference == getApplication<App>().resources.getString(R.string.best_quality)){
formats.last { !it.format_note.contains("audio", ignoreCase = true) } theFormats.last { !it.format_note.contains("audio", ignoreCase = true) }
} }
try{ try{
formats.last { format -> format.format_note.contains(qualityPreference!!.substring(0, qualityPreference.length -1)) } theFormats.last { format -> format.format_note.contains(qualityPreference!!.substring(0, qualityPreference.length - 1)) }
}catch (e: Exception){ }catch (e: Exception){
formats.last { !it.format_note.contains("audio", ignoreCase = true) } theFormats.last { !it.format_note.contains("audio", ignoreCase = true) }
} }
}catch (e: Exception){ }catch (e: Exception){
bestVideoFormat bestVideoFormat

View file

@ -266,7 +266,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
.inflate(R.layout.search_suggestion_item, null) .inflate(R.layout.search_suggestion_item, null)
val textView = v.findViewById<TextView>(R.id.suggestion_text) val textView = v.findViewById<TextView>(R.id.suggestion_text)
textView.text = suggestions[i] textView.text = suggestions[i]
textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_refresh, 0, 0, 0) textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_restore, 0, 0, 0)
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
searchHistoryLinearLayout!!.addView( searchHistoryLinearLayout!!.addView(
v v
@ -291,6 +291,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button) val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener { mb.setOnClickListener {
searchView.setText(textView.text) searchView.setText(textView.text)
searchView.editText.setSelection(searchView.editText.length())
} }
} }
searchHistoryLinearLayout!!.visibility = VISIBLE searchHistoryLinearLayout!!.visibility = VISIBLE
@ -315,6 +316,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
val mb = v.findViewById<ImageButton>(R.id.set_search_query_button) val mb = v.findViewById<ImageButton>(R.id.set_search_query_button)
mb.setOnClickListener { mb.setOnClickListener {
searchView.setText(textView.text) searchView.setText(textView.text)
searchView.editText.setSelection(searchView.editText.length())
} }
} }
searchSuggestionsLinearLayout!!.visibility = VISIBLE searchSuggestionsLinearLayout!!.visibility = VISIBLE
@ -437,23 +439,27 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
} catch (e: Exception) {""} } catch (e: Exception) {""}
if (viewIdName.isNotEmpty()) { if (viewIdName.isNotEmpty()) {
if (viewIdName == "downloadSelected") { if (viewIdName == "downloadSelected") {
val downloadList = downloadViewModel.turnResultItemsToDownloadItems(selectedObjects!!) lifecycleScope.launch {
if (sharedPreferences!!.getBoolean("download_card", true)) { val downloadList = withContext(Dispatchers.IO){
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList()) downloadViewModel.turnResultItemsToDownloadItems(selectedObjects!!)
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") }
} else { if (sharedPreferences!!.getBoolean("download_card", true)) {
lifecycleScope.launch { val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
} else {
downloadViewModel.queueDownloads(downloadList) downloadViewModel.queueDownloads(downloadList)
} }
} }
} }
if (viewIdName == "downloadAll") { if (viewIdName == "downloadAll") {
val downloadList = downloadViewModel.turnResultItemsToDownloadItems(resultsList!!) lifecycleScope.launch {
if (sharedPreferences!!.getBoolean("download_card", true)) { val downloadList = withContext(Dispatchers.IO){
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList()) downloadViewModel.turnResultItemsToDownloadItems(resultsList!!)
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet") }
} else { if (sharedPreferences!!.getBoolean("download_card", true)) {
lifecycleScope.launch { val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
} else {
downloadViewModel.queueDownloads(downloadList) downloadViewModel.queueDownloads(downloadList)
} }
} }

View file

@ -22,6 +22,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.receiver.ShareActivity import com.deniscerri.ytdlnis.receiver.ShareActivity
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.* import java.util.*
@ -74,7 +75,7 @@ class SelectPlaylistItemsBottomSheetDialog(private val items: List<ResultItem?>,
selectedText = view.findViewById<Button>(R.id.selected) selectedText = view.findViewById<Button>(R.id.selected)
selectedText.text = "0 ${resources.getString(R.string.selected)}" selectedText.text = "0 ${resources.getString(R.string.selected)}"
val checkAll = view.findViewById<Button>(R.id.check_all) val checkAll = view.findViewById<FloatingActionButton>(R.id.check_all)
checkAll!!.setOnClickListener { checkAll!!.setOnClickListener {
if (listAdapter.getCheckedItems().size != items.size){ if (listAdapter.getCheckedItems().size != items.size){
listAdapter.checkAll() listAdapter.checkAll()

View file

@ -44,6 +44,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
private var logDownloads: SwitchPreferenceCompat? = null private var logDownloads: SwitchPreferenceCompat? = null
private var sponsorblockFilters: MultiSelectListPreference? = null private var sponsorblockFilters: MultiSelectListPreference? = null
private var filenameTemplate: EditTextPreference? = null private var filenameTemplate: EditTextPreference? = null
private var restrictFilenames: SwitchPreferenceCompat? = null
private var mtime: SwitchPreferenceCompat? = null private var mtime: SwitchPreferenceCompat? = null
private var embedSubtitles: SwitchPreferenceCompat? = null private var embedSubtitles: SwitchPreferenceCompat? = null
private var embedThumbnail: SwitchPreferenceCompat? = null private var embedThumbnail: SwitchPreferenceCompat? = null
@ -106,6 +107,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
mtime = findPreference("mtime") mtime = findPreference("mtime")
embedSubtitles = findPreference("embed_subtitles") embedSubtitles = findPreference("embed_subtitles")
filenameTemplate = findPreference("file_name_template") filenameTemplate = findPreference("file_name_template")
restrictFilenames = findPreference("restrict_filenames")
embedThumbnail = findPreference("embed_thumbnail") embedThumbnail = findPreference("embed_thumbnail")
addChapters = findPreference("add_chapters") addChapters = findPreference("add_chapters")
writeThumbnail = findPreference("write_thumbnail") writeThumbnail = findPreference("write_thumbnail")
@ -162,6 +164,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
editor.putBoolean("log_downloads", logDownloads!!.isChecked) editor.putBoolean("log_downloads", logDownloads!!.isChecked)
editor.putStringSet("sponsorblock_filters", sponsorblockFilters!!.values) editor.putStringSet("sponsorblock_filters", sponsorblockFilters!!.values)
editor.putString("file_name_template", filenameTemplate!!.text) editor.putString("file_name_template", filenameTemplate!!.text)
editor.putBoolean("restrict_filenames", restrictFilenames!!.isChecked)
editor.putBoolean("mtime", mtime!!.isChecked) editor.putBoolean("mtime", mtime!!.isChecked)
editor.putBoolean("embed_subtitles", embedSubtitles!!.isChecked) editor.putBoolean("embed_subtitles", embedSubtitles!!.isChecked)
editor.putBoolean("embed_thumbnail", embedThumbnail!!.isChecked) editor.putBoolean("embed_thumbnail", embedThumbnail!!.isChecked)
@ -337,6 +340,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
editor.apply() editor.apply()
true true
} }
restrictFilenames!!.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
val embed = newValue as Boolean
editor.putBoolean("restrict_filenames", embed)
editor.apply()
true
}
mtime!!.onPreferenceChangeListener = mtime!!.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
val embed = newValue as Boolean val embed = newValue as Boolean

View file

@ -280,6 +280,9 @@ class InfoUtil(context: Context) {
val id = obj.getString("videoId") val id = obj.getString("videoId")
val title = obj.getString("title").toString() val title = obj.getString("title").toString()
val author = obj.getString("author").toString() val author = obj.getString("author").toString()
if (author.isNullOrBlank()) throw Exception()
val duration = formatIntegerDuration(obj.getInt("lengthSeconds")) val duration = formatIntegerDuration(obj.getInt("lengthSeconds"))
val thumb = "https://i.ytimg.com/vi/$id/hqdefault.jpg" val thumb = "https://i.ytimg.com/vi/$id/hqdefault.jpg"
val url = "https://www.youtube.com/watch?v=$id" val url = "https://www.youtube.com/watch?v=$id"

View file

@ -68,7 +68,8 @@ class DownloadWorker(
val type = downloadItem.type val type = downloadItem.type
val downloadLocation = downloadItem.downloadPath val downloadLocation = downloadItem.downloadPath
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""") val titleRegex = Regex("[^A-Za-z\\d ]")
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${titleRegex.replace(downloadItem.title, "")}##${downloadItem.type}""")
tempFolder.append("##${downloadItem.format.format_id}") tempFolder.append("##${downloadItem.format.format_id}")
val tempFileDir = File(tempFolder.toString()) val tempFileDir = File(tempFolder.toString())
tempFileDir.delete() tempFileDir.delete()
@ -110,7 +111,9 @@ class DownloadWorker(
if (downloadItem.customFileNameTemplate.isEmpty()) downloadItem.customFileNameTemplate = "%(uploader)s - %(title)s" if (downloadItem.customFileNameTemplate.isEmpty()) downloadItem.customFileNameTemplate = "%(uploader)s - %(title)s"
} }
request.addOption("--restrict-filenames") if (sharedPreferences.getBoolean("restrict_filenames", true)) {
request.addOption("--restrict-filenames")
}
when(type){ when(type){
DownloadViewModel.Type.audio -> { DownloadViewModel.Type.audio -> {
@ -210,8 +213,7 @@ class DownloadWorker(
runCatching { runCatching {
val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false) val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false)
val logFolder = File(context.filesDir.absolutePath + "/logs") val logFolder = File(context.filesDir.absolutePath + "/logs")
val regex = Regex("[^A-Za-z\\d ]") val logFile = File(context.filesDir.absolutePath + """/logs/${downloadItem.id} - ${titleRegex.replace(downloadItem.title, "")}##${downloadItem.type}##${downloadItem.format.format_id}.log""")
val logFile = File(context.filesDir.absolutePath + """/logs/${downloadItem.id} - ${regex.replace(downloadItem.title, "")}##${downloadItem.type}##${downloadItem.format.format_id}.log""")
Log.e("aa", logFile.name) Log.e("aa", logFile.name)
if (logDownloads){ if (logDownloads){
logFolder.mkdirs() logFolder.mkdirs()

View file

@ -0,0 +1,14 @@
<vector android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:rotation="270"
android:pivotY="12"
android:pivotX="12"
>
<path android:fillColor="?android:textColorPrimary" android:pathData="M6,6l0,2l8.59,0l-9.59,9.59l1.41,1.41l9.59,-9.59l0,8.59l2,0l0,-12z"/>
</group>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M18.41,5.8L17.2,4.59c-0.78,-0.78 -2.05,-0.78 -2.83,0l-2.68,2.68L3,15.96V20h4.04l8.74,-8.74 2.63,-2.63c0.79,-0.78 0.79,-2.05 0,-2.83zM6.21,18H5v-1.21l8.66,-8.66 1.21,1.21L6.21,18zM11,20l4,-4h6v4H11z"/>
</vector>

View file

@ -50,6 +50,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:orientation="vertical" android:orientation="vertical"
android:dividerPadding="5dp"
app:layout_constraintBottom_toTopOf="@+id/linearlayout2_horizontalscrollview" app:layout_constraintBottom_toTopOf="@+id/linearlayout2_horizontalscrollview"
app:layout_constraintEnd_toStartOf="@+id/active_download_cancel" app:layout_constraintEnd_toStartOf="@+id/active_download_cancel"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -59,39 +60,32 @@
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:paddingStart="10dp"
android:scrollbars="none"
android:paddingTop="10dp" android:paddingTop="10dp"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:shadowColor="@color/black" android:paddingStart="10dp"
android:textSize="17sp"
android:textColor="@color/white"
android:textStyle="bold"
android:shadowRadius="2"
android:shadowDx="4" android:shadowDx="4"
android:shadowDy="4" android:shadowDy="4"
android:shadowRadius="2" android:shadowColor="@color/black" />
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
<TextView <TextView
android:id="@+id/author" android:id="@+id/author"
android:layout_width="296dp" android:layout_width="match_parent"
android:layout_height="20dp" android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="bottom" android:gravity="bottom"
android:maxLines="1"
android:layout_marginTop="5dp"
android:paddingStart="10dp"
android:scrollbars="none"
android:paddingEnd="10dp" android:paddingEnd="10dp"
android:paddingBottom="5dp" android:paddingBottom="5dp"
android:shadowColor="@color/black" android:paddingStart="10dp"
android:textSize="12sp"
android:textColor="@color/white"
android:textStyle="bold"
android:shadowRadius="1.5"
android:shadowDx="4" android:shadowDx="4"
android:shadowDy="4" android:shadowDy="4"
android:shadowRadius="1.5" android:shadowColor="@color/black" />
android:textColor="@color/white"
android:textSize="13sp"
android:textStyle="bold" />
</LinearLayout> </LinearLayout>
@ -103,15 +97,17 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollbars="none" android:scrollbars="none"
app:layout_constraintBottom_toTopOf="@+id/output" app:layout_constraintBottom_toTopOf="@+id/output"
app:layout_constraintStart_toStartOf="parent"> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/active_download_cancel"
app:layout_constraintVertical_bias="1.0">
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:id="@+id/linearLayout2" android:id="@+id/linearLayout2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="horizontal"> android:orientation="horizontal"
android:paddingHorizontal="10dp">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/type" android:id="@+id/type"
@ -157,7 +153,6 @@
</HorizontalScrollView> </HorizontalScrollView>
<TextView <TextView
android:id="@+id/output" android:id="@+id/output"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -1,19 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/downloads_card_constraintLayout" android:id="@+id/downloads_card_constraintLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<com.google.android.material.card.MaterialCardView <FrameLayout
android:id="@+id/download_card_view" android:id="@+id/download_card_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="120dp" app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
android:layout_height="wrap_content"
android:layout_margin="10dp" android:layout_margin="10dp"
android:checkable="true" android:checkable="true"
app:cardCornerRadius="10dp" android:clickable="true"
app:cardMaxElevation="12dp" android:focusable="true"
app:cardElevation="5dp" android:background="?android:attr/selectableItemBackground"
app:cardPreventCornerOverlap="true" app:cardPreventCornerOverlap="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@ -21,149 +23,172 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp"> app:strokeWidth="0dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/downloads_image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<LinearLayout <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/title_author" android:id="@+id/downloads_image_view"
android:layout_width="0dp" android:layout_width="0dp"
android:paddingStart="10dp" android:layout_height="0dp"
android:paddingEnd="10dp" app:layout_constraintHorizontal_weight="0.3"
android:layout_height="wrap_content" android:adjustViewBounds="true"
android:orientation="vertical" android:scaleType="centerCrop"
app:layout_constraintEnd_toStartOf="@+id/action_button" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintEnd_toStartOf="@+id/download_item_data"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#80000000"
android:clickable="false"
android:layout_margin="5dp"
android:ellipsize="end"
android:gravity="center"
android:textStyle="bold"
android:maxLength="17"
android:maxLines="1"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textColor="@color/white"
android:textSize="12sp"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="@+id/downloads_image_view"
app:layout_constraintEnd_toEndOf="@+id/downloads_image_view" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/download_item_data"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHorizontal_weight="0.7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/downloads_image_view"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:paddingHorizontal="5dp"
android:scrollbars="none" android:scrollbars="none"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:shadowColor="@color/black" android:shadowColor="@color/black"
android:shadowDx="4" android:shadowDx="4"
android:shadowDy="4" android:shadowDy="4"
android:shadowRadius="2" android:shadowRadius="2"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="15sp" android:textSize="15sp"
android:textStyle="bold" /> android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/action_button"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView <HorizontalScrollView
android:id="@+id/subtitle"
android:layout_width="296dp"
android:layout_height="20dp"
android:ellipsize="end"
android:gravity="bottom"
android:maxLines="1"
android:scrollbars="none"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
android:textColor="@color/white"
android:textSize="11sp"
android:textStyle="bold" />
</LinearLayout>
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingStart="10dp"
android:paddingEnd="0dp"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_author"
app:layout_constraintVertical_bias="1.0">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent"> android:layout_height="wrap_content"
android:gravity="bottom"
android:paddingStart="5dp"
android:paddingEnd="0dp"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/action_button"
app:layout_constraintVertical_bias="1.0">
<com.google.android.material.chip.Chip <LinearLayout
android:id="@+id/format_note"
style="@style/Widget.Material3.FloatingActionButton.Large.Primary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:clickable="false"
android:ellipsize="end"
android:gravity="center"
android:maxLines="1"
android:minWidth="30dp"
android:paddingHorizontal="10dp"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.chip.Chip <TextView
android:id="@+id/codec" style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary" android:background="?attr/colorSecondary"
android:layout_width="wrap_content" android:id="@+id/format_note"
android:layout_height="wrap_content" android:layout_marginEnd="5dp"
android:clickable="false" android:maxLength="17"
android:gravity="center" android:layout_width="wrap_content"
android:minWidth="30dp" android:layout_height="wrap_content"
app:cornerRadius="10dp" android:clickable="false"
app:layout_constraintBottom_toBottomOf="parent" android:ellipsize="end"
app:layout_constraintStart_toStartOf="parent" android:gravity="center"
app:layout_constraintTop_toTopOf="parent" /> android:textSize="12sp"
android:maxLines="1"
android:minWidth="30dp"
android:textStyle="bold"
android:paddingHorizontal="5dp"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.chip.Chip <TextView
android:id="@+id/file_size" style="@style/Widget.Material3.FloatingActionButton.Large.Tertiary"
style="@style/Widget.Material3.FloatingActionButton.Large.Tertiary" android:background="?attr/colorSecondary"
android:layout_width="wrap_content" android:id="@+id/codec"
android:layout_height="wrap_content" android:layout_marginEnd="5dp"
android:clickable="false" android:layout_width="wrap_content"
android:gravity="center" android:layout_height="wrap_content"
android:minWidth="30dp" android:clickable="false"
app:cornerRadius="10dp" android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent" android:minWidth="30dp"
app:layout_constraintStart_toStartOf="parent" android:textSize="12sp"
app:layout_constraintTop_toTopOf="parent" /> android:textStyle="bold"
android:paddingHorizontal="5dp"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:background="?attr/colorPrimaryInverse"
android:id="@+id/file_size"
android:layout_marginEnd="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="center"
android:textStyle="bold"
android:paddingHorizontal="5dp"
android:minWidth="30dp"
app:cornerRadius="10dp"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</com.google.android.material.chip.ChipGroup> </LinearLayout>
</HorizontalScrollView> </HorizontalScrollView>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/action_button" android:id="@+id/action_button"
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary" style="?attr/materialIconButtonStyle"
android:layout_width="55dp" android:layout_width="wrap_content"
android:layout_height="55dp" android:layout_height="wrap_content"
android:layout_margin="10dp" app:cornerRadius="10dp"
android:layout_marginEnd="8dp" app:icon="@drawable/ic_video"
app:cornerRadius="10dp" app:layout_constraintBottom_toBottomOf="parent"
app:icon="@drawable/ic_video" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintVertical_bias="0.0" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.155" /> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -99,9 +99,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:paddingTop="10dp" android:paddingTop="10dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="80dp" android:paddingBottom="70dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

View file

@ -65,7 +65,8 @@
android:clickable="false" android:clickable="false"
android:gravity="center" android:gravity="center"
android:minWidth="30dp" android:minWidth="30dp"
android:paddingHorizontal="10dp" android:textStyle="bold"
android:paddingHorizontal="5dp"
app:cornerRadius="10dp" app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -81,7 +82,8 @@
android:clickable="false" android:clickable="false"
android:gravity="center" android:gravity="center"
android:minWidth="30dp" android:minWidth="30dp"
android:paddingHorizontal="10dp" android:textStyle="bold"
android:paddingHorizontal="5dp"
app:cornerRadius="10dp" app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View file

@ -4,36 +4,108 @@
android:id="@+id/playlist_card_constraintLayout" android:id="@+id/playlist_card_constraintLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_marginBottom="10dp" android:layout_marginBottom="10dp"
android:layout_height="50dp"> android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/download_card_view"
android:layout_width="0dp"
android:layout_marginStart="10dp"
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
android:layout_height="wrap_content"
android:checkable="true"
android:clickable="true"
android:focusable="true"
app:cardPreventCornerOverlap="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/checkBox"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/downloads_image_view"
android:clickable="false"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHorizontal_weight="0.3"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintEnd_toStartOf="@+id/download_item_data"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
/>
<TextView
android:id="@+id/duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#80000000"
android:clickable="false"
android:layout_margin="5dp"
android:ellipsize="end"
android:gravity="center"
android:textStyle="bold"
android:maxLength="17"
android:maxLines="1"
android:minWidth="30dp"
android:paddingHorizontal="5dp"
android:textColor="@color/white"
android:textSize="12sp"
app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="@+id/downloads_image_view"
app:layout_constraintEnd_toEndOf="@+id/downloads_image_view" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/download_item_data"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHorizontal_weight="0.7"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/downloads_image_view"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:paddingHorizontal="10dp"
android:scrollbars="none"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="2"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
<CheckBox <CheckBox
android:id="@+id/checkBox" android:id="@+id/checkBox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/downloads_image_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintDimensionRatio="H,16:9"
android:layout_marginEnd="10dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
app:layout_constraintStart_toEndOf="@+id/checkBox" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="15dp"
android:lines="2"
android:maxLines="2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/downloads_image_view"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -57,7 +57,7 @@
android:focusable="true" android:focusable="true"
android:clickable="true" android:clickable="true"
android:layout_height="match_parent" android:layout_height="match_parent"
android:src="@drawable/ic_arrow_up" android:src="@drawable/ic_arrow_outward"
android:layout_weight="0.01" android:layout_weight="0.01"
/> />

View file

@ -8,7 +8,7 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
android:elevation="10dp" android:elevation="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -19,32 +19,24 @@
android:id="@+id/bottomAppBar" android:id="@+id/bottomAppBar"
style="@style/Widget.Material3.BottomAppBar" style="@style/Widget.Material3.BottomAppBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="wrap_content"
android:layout_gravity="bottom"> android:layout_gravity="bottom">
<Button
style="?attr/materialIconButtonStyle"
android:id="@+id/check_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_select_all" />
<TextView <TextView
android:id="@+id/selected" android:id="@+id/selected"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:textStyle="bold" android:textStyle="bold"
android:paddingStart="17dp"
android:paddingEnd="0dp"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
</com.google.android.material.bottomappbar.BottomAppBar> </com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/edit_selected" android:id="@+id/check_all"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone" app:layout_anchor="@id/bottomAppBar"
app:srcCompat="@drawable/ic_edit" /> app:srcCompat="@drawable/ic_select_all" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
@ -100,7 +92,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="70dp" android:paddingBottom="80dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

View file

@ -181,4 +181,6 @@
<string name="ytdl_version">yt-dlp Version</string> <string name="ytdl_version">yt-dlp Version</string>
<string name="freespace">Free space</string> <string name="freespace">Free space</string>
<string name="link_you_copied">Link you copied</string> <string name="link_you_copied">Link you copied</string>
<string name="restrict_filenames">Restrict Filenames</string>
<string name="restrict_filenames_summary"><![CDATA[Restrict filenames to only ASCII characters, and avoid \"&\" and spaces in filenames]]></string>
</resources> </resources>

View file

@ -48,4 +48,9 @@
<item name="android:layout_marginStart">5dp</item> <item name="android:layout_marginStart">5dp</item>
</style> </style>
<style name="ShapeAppearanceOverlay.Avatar" parent="ShapeAppearance.MaterialComponents.SmallComponent">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">5dp</item>
</style>
</resources> </resources>

View file

@ -10,7 +10,7 @@
app:icon="@drawable/ic_terminal" app:icon="@drawable/ic_terminal"
app:key="run_command" app:key="run_command"
app:title="@string/terminal"> app:title="@string/terminal">
<intent android:action="ytdlnis.CustomCommandActivity" /> <intent android:action="ytdlnis.TerminalActivity" />
</Preference> </Preference>
<Preference <Preference

View file

@ -143,6 +143,14 @@
app:defaultValue="%(uploader)s - %(title)s" app:defaultValue="%(uploader)s - %(title)s"
app:title="@string/file_name_template" /> app:title="@string/file_name_template" />
<SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="true"
app:icon="@drawable/if_file_rename"
app:key="restrict_filenames"
app:summary="@string/restrict_filenames_summary"
app:title="@string/restrict_filenames" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch" android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="false" app:defaultValue="false"