even more features
This commit is contained in:
parent
7754e6f1bd
commit
1e329d3a8a
25 changed files with 1312 additions and 85 deletions
|
|
@ -139,7 +139,7 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs_nio:2.1.2"
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs_nio:2.1.4"
|
||||
// implementation "com.github.yausername.youtubedl-android:library:$youtubedlAndroidVer"
|
||||
// implementation "com.github.yausername.youtubedl-android:ffmpeg:$youtubedlAndroidVer"
|
||||
// implementation "com.github.yausername.youtubedl-android:aria2c:$youtubedlAndroidVer"
|
||||
|
|
@ -150,16 +150,16 @@ dependencies {
|
|||
implementation "io.github.junkfood02.youtubedl-android:aria2c:0.17.2"
|
||||
|
||||
implementation "androidx.appcompat:appcompat:$appCompatVer"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||
implementation "androidx.constraintlayout:constraintlayout:2.2.0"
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.4.0'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$navVer"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$navVer"
|
||||
implementation 'androidx.core:core-ktx:1.13.1'
|
||||
implementation 'androidx.core:core-ktx:1.15.0'
|
||||
implementation 'androidx.test.ext:junit-ktx:1.2.1'
|
||||
implementation 'androidx.compose.ui:ui-android:1.7.4'
|
||||
implementation 'androidx.compose.ui:ui-android:1.7.6'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
testImplementation "junit:junit:$junitVer"
|
||||
androidTestImplementation "junit:junit:$junitVer"
|
||||
|
|
@ -184,7 +184,7 @@ dependencies {
|
|||
implementation 'androidx.paging:paging-runtime-ktx:3.3.2'
|
||||
implementation "androidx.room:room-paging:$roomVer"
|
||||
androidTestImplementation "androidx.room:room-testing:$roomVer"
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.6'
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.7'
|
||||
implementation "androidx.compose.runtime:runtime:$composeVer"
|
||||
androidTestImplementation 'com.google.truth:truth:1.1.5'
|
||||
|
||||
|
|
@ -196,7 +196,7 @@ dependencies {
|
|||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
|
||||
implementation 'it.xabaras.android:recyclerview-swipedecorator:1.4'
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.6"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7"
|
||||
implementation "com.neoutils.highlight:highlight-view:2.2.0"
|
||||
|
||||
// For media playback using ExoPlayer
|
||||
|
|
@ -212,8 +212,8 @@ dependencies {
|
|||
implementation "com.anggrayudi:storage:1.5.5"
|
||||
implementation 'me.zhanghai.android.fastscroll:library:1.3.0'
|
||||
implementation 'com.google.accompanist:accompanist-webview:0.30.1'
|
||||
implementation 'androidx.compose.material3:material3-android:1.3.0'
|
||||
implementation 'androidx.compose.material3:material3-android:1.3.1'
|
||||
implementation "io.noties.markwon:core:4.6.2"
|
||||
implementation("org.greenrobot:eventbus:3.3.1")
|
||||
implementation("com.github.teamnewpipe:newpipeextractor:0.24.2")
|
||||
implementation("com.github.teamnewpipe:newpipeextractor:0.24.4")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.deniscerri.ytdl.database.models
|
||||
|
||||
data class YoutubePlayerClientItem(
|
||||
var playerClient: String,
|
||||
var poTokens: MutableList<YoutubePoTokenItem>,
|
||||
var enabled: Boolean = true
|
||||
)
|
||||
|
||||
data class YoutubePoTokenItem(
|
||||
var context: String,
|
||||
var token: String
|
||||
)
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
package com.deniscerri.ytdl.ui.adapter
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.database.models.CookieItem
|
||||
import com.deniscerri.ytdl.database.models.Format
|
||||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdl.databinding.FormatItemBinding
|
||||
import com.deniscerri.ytdl.ui.adapter.HistoryPaginatedAdapter.ViewHolder
|
||||
import com.deniscerri.ytdl.util.Extensions.popup
|
||||
import com.deniscerri.ytdl.util.UiUtil
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
|
||||
class FormatAdapter(onItemClickListener: OnItemClickListener, activity: Activity, private val downloadType: DownloadViewModel.Type) : ListAdapter<Format?, FormatAdapter.ViewHolder>(AsyncDifferConfig.Builder(
|
||||
DIFF_CALLBACK
|
||||
).build()) {
|
||||
private val onItemClickListener: OnItemClickListener
|
||||
private val activity: Activity
|
||||
private var selectedVideoFormat: Format?
|
||||
private val selectedAudioFormats: MutableList<Format>
|
||||
private val usingGrid: Boolean
|
||||
|
||||
|
||||
init {
|
||||
this.onItemClickListener = onItemClickListener
|
||||
this.activity = activity
|
||||
this.selectedVideoFormat = null
|
||||
this.usingGrid = false
|
||||
this.selectedAudioFormats = mutableListOf()
|
||||
}
|
||||
|
||||
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||
val item: MaterialCardView
|
||||
|
||||
init {
|
||||
item = itemView.findViewById(R.id.format_card_constraintLayout)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return if (usingGrid){
|
||||
val cardView = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.format_item_grid, parent, false)
|
||||
|
||||
ViewHolder(
|
||||
cardView,
|
||||
onItemClickListener
|
||||
)
|
||||
}else{
|
||||
val cardView = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.format_item, parent, false)
|
||||
|
||||
ViewHolder(
|
||||
cardView,
|
||||
onItemClickListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = getItem(position) ?: return
|
||||
val card = holder.item
|
||||
card.popup()
|
||||
UiUtil.populateFormatCard(activity, card, item)
|
||||
card.setOnClickListener {
|
||||
when(downloadType) {
|
||||
DownloadViewModel.Type.audio -> {
|
||||
onItemClickListener.onItemClick(item)
|
||||
}
|
||||
DownloadViewModel.Type.video -> {
|
||||
if(item.isAudio()) {
|
||||
if (card.isChecked) {
|
||||
selectedAudioFormats.remove(item)
|
||||
}else {
|
||||
selectedAudioFormats.add(item)
|
||||
}
|
||||
}else {
|
||||
if (card.isChecked) {
|
||||
onItemClickListener.onItemClick(item)
|
||||
}else {
|
||||
selectedVideoFormat = item
|
||||
card.isChecked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun Format.isAudio() : Boolean {
|
||||
return this.vcodec.isNotBlank() && this.vcodec != "none"
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onItemClick(item: Format)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DIFF_CALLBACK: DiffUtil.ItemCallback<Format> = object : DiffUtil.ItemCallback<Format>() {
|
||||
override fun areItemsTheSame(oldItem: Format, newItem: Format): Boolean {
|
||||
return oldItem.format_id == newItem.format_id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: Format, newItem: Format): Boolean {
|
||||
return oldItem.format_id == newItem.format_id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
package com.deniscerri.ytdl.ui.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.database.models.CommandTemplate
|
||||
import com.deniscerri.ytdl.database.models.YoutubePlayerClientItem
|
||||
import com.deniscerri.ytdl.util.Extensions.popup
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
|
||||
class YoutubePlayerClientAdapter(onItemClickListener: OnItemClickListener, activity: Activity, private var itemTouchHelper: ItemTouchHelper) : ListAdapter<YoutubePlayerClientItem?, YoutubePlayerClientAdapter.ViewHolder>(AsyncDifferConfig.Builder(
|
||||
DIFF_CALLBACK
|
||||
).build()) {
|
||||
private val onItemClickListener: OnItemClickListener
|
||||
private val activity: Activity
|
||||
var showDragHandle: Boolean
|
||||
private val sharedPreferences: SharedPreferences
|
||||
|
||||
init {
|
||||
this.onItemClickListener = onItemClickListener
|
||||
this.activity = activity
|
||||
this.showDragHandle = false
|
||||
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
}
|
||||
|
||||
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||
val item: MaterialCardView
|
||||
|
||||
init {
|
||||
item = itemView.findViewById(R.id.card)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val cardView = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.player_client_item, parent, false)
|
||||
return ViewHolder(cardView, onItemClickListener)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = getItem(position)!!
|
||||
holder.itemView.tag = item.playerClient
|
||||
val card = holder.item
|
||||
val title = card.findViewById<TextView>(R.id.title)
|
||||
title.text = item.playerClient
|
||||
|
||||
val content = card.findViewById<TextView>(R.id.content)
|
||||
if (item.poTokens.isNotEmpty()) {
|
||||
val text = item.poTokens.joinToString("\n") { "PO Token (${it.context}): ${it.token}" }
|
||||
content.text = text
|
||||
}else {
|
||||
content.isVisible = false
|
||||
}
|
||||
|
||||
val switch = card.findViewById<MaterialSwitch>(R.id.materialSwitch)
|
||||
switch.isChecked = item.enabled
|
||||
switch.setOnClickListener {
|
||||
onItemClickListener.onStatusToggle(item, switch.isChecked, position)
|
||||
}
|
||||
|
||||
//DRAG HANDLE
|
||||
val dragView = card.findViewById<View>(R.id.drag_view)
|
||||
dragView.isVisible = showDragHandle
|
||||
dragView.setOnTouchListener { view, motionEvent ->
|
||||
view.performClick()
|
||||
if (motionEvent.actionMasked == MotionEvent.ACTION_DOWN){
|
||||
itemTouchHelper.startDrag(holder)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
card.setOnClickListener {
|
||||
onItemClickListener.onItemClick(item, position)
|
||||
}
|
||||
|
||||
card.setOnLongClickListener {
|
||||
onItemClickListener.onDeleteClick(item, position)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun toggleShowDragHandle(){
|
||||
showDragHandle = !showDragHandle
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun onItemClick(item: YoutubePlayerClientItem, index: Int)
|
||||
fun onStatusToggle(item: YoutubePlayerClientItem, enabled: Boolean, index: Int)
|
||||
fun onDeleteClick(item: YoutubePlayerClientItem, index: Int)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DIFF_CALLBACK: DiffUtil.ItemCallback<YoutubePlayerClientItem> = object : DiffUtil.ItemCallback<YoutubePlayerClientItem>() {
|
||||
override fun areItemsTheSame(oldItem: YoutubePlayerClientItem, newItem: YoutubePlayerClientItem): Boolean {
|
||||
return oldItem.playerClient == newItem.playerClient
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: YoutubePlayerClientItem, newItem: YoutubePlayerClientItem): Boolean {
|
||||
return oldItem.playerClient == newItem.playerClient && oldItem.enabled == newItem.enabled && oldItem.poTokens.joinToString(
|
||||
"\n"
|
||||
) { it.token } == newItem.poTokens.joinToString(
|
||||
"\n"
|
||||
) { it.token }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,13 +2,18 @@ package com.deniscerri.ytdl.ui.downloadcard
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.*
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import android.widget.*
|
||||
import android.widget.Button
|
||||
import android.widget.GridLayout
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isVisible
|
||||
|
|
@ -52,8 +57,8 @@ class FormatSelectionBottomSheetDialog(
|
|||
private lateinit var downloadViewModel: DownloadViewModel
|
||||
private lateinit var resultViewModel: ResultViewModel
|
||||
private lateinit var sharedPreferences: SharedPreferences
|
||||
private lateinit var videoFormatList : LinearLayout
|
||||
private lateinit var audioFormatList : LinearLayout
|
||||
private lateinit var videoFormatList : GridLayout
|
||||
private lateinit var audioFormatList : GridLayout
|
||||
private lateinit var okBtn : Button
|
||||
private lateinit var refreshBtn: Button
|
||||
private lateinit var videoTitle : TextView
|
||||
|
|
@ -80,6 +85,8 @@ class FormatSelectionBottomSheetDialog(
|
|||
private lateinit var genericAudioFormats : List<Format>
|
||||
private lateinit var genericVideoFormats : List<Format>
|
||||
|
||||
private var usingGrid: Boolean = false
|
||||
|
||||
enum class FormatSorting {
|
||||
filesize, container, codec, id
|
||||
}
|
||||
|
|
@ -135,6 +142,7 @@ class FormatSelectionBottomSheetDialog(
|
|||
sortBy = FormatSorting.valueOf(sharedPreferences.getString("format_order", "filesize")!!)
|
||||
filterBy = FormatCategory.valueOf(sharedPreferences.getString("format_filter", "ALL")!!)
|
||||
filterBtn = view.findViewById(R.id.format_filter)
|
||||
usingGrid = sharedPreferences.getBoolean("format_list_grid", false)
|
||||
|
||||
dialog.setOnShowListener {
|
||||
behavior = BottomSheetBehavior.from(view.parent as View)
|
||||
|
|
@ -438,7 +446,32 @@ class FormatSelectionBottomSheetDialog(
|
|||
}
|
||||
|
||||
|
||||
//format layout
|
||||
val listLayout = filterSheet.findViewById<TextView>(R.id.layout_list)!!
|
||||
val gridLayout = filterSheet.findViewById<TextView>(R.id.layout_grid)!!
|
||||
|
||||
if (usingGrid) {
|
||||
listLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty, 0,0,0)
|
||||
gridLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_check, 0,0,0)
|
||||
}else{
|
||||
gridLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty, 0,0,0)
|
||||
listLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_check, 0,0,0)
|
||||
}
|
||||
|
||||
listLayout.setOnClickListener {
|
||||
usingGrid = false
|
||||
gridLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty, 0,0,0)
|
||||
listLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_check, 0,0,0)
|
||||
addFormatsToView()
|
||||
filterSheet.dismiss()
|
||||
}
|
||||
gridLayout.setOnClickListener {
|
||||
usingGrid = true
|
||||
listLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty, 0,0,0)
|
||||
gridLayout.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_check, 0,0,0)
|
||||
addFormatsToView()
|
||||
filterSheet.dismiss()
|
||||
}
|
||||
|
||||
val displayMetrics = DisplayMetrics()
|
||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
|
|
@ -535,8 +568,6 @@ class FormatSelectionBottomSheetDialog(
|
|||
|
||||
|
||||
val canMultiSelectAudio = items.first()?.type == Type.video && finalFormats.find { it.vcodec.isBlank() || it.vcodec == "none" } != null
|
||||
videoFormatList.removeAllViews()
|
||||
audioFormatList.removeAllViews()
|
||||
|
||||
if (!canMultiSelectAudio) {
|
||||
audioFormatList.visibility = View.GONE
|
||||
|
|
@ -561,6 +592,14 @@ class FormatSelectionBottomSheetDialog(
|
|||
videoFormatList.removeAllViews()
|
||||
audioFormatList.removeAllViews()
|
||||
|
||||
if (usingGrid) {
|
||||
videoFormatList.columnCount = 2
|
||||
audioFormatList.columnCount = 2
|
||||
}else{
|
||||
videoFormatList.columnCount = 1
|
||||
audioFormatList.columnCount = 1
|
||||
}
|
||||
|
||||
if (finalFormats.isEmpty()){
|
||||
finalFormats = if (items.first()?.type == Type.audio){
|
||||
genericAudioFormats
|
||||
|
|
@ -571,7 +610,23 @@ class FormatSelectionBottomSheetDialog(
|
|||
|
||||
for (i in 0.. finalFormats.lastIndex){
|
||||
val format = finalFormats[i]
|
||||
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
||||
lateinit var formatItem: View
|
||||
|
||||
if (usingGrid){
|
||||
formatItem = LayoutInflater.from(context).inflate(R.layout.format_item_grid, null)
|
||||
formatItem.layoutParams = GridLayout.LayoutParams(
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f),
|
||||
GridLayout.spec(GridLayout.UNDEFINED, 1f)).apply {
|
||||
width = 0
|
||||
}
|
||||
}else{
|
||||
formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
||||
formatItem.layoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
1.0f
|
||||
)
|
||||
}
|
||||
formatItem.tag = "${format.format_id}${format.format_note}"
|
||||
UiUtil.populateFormatCard(requireContext(), formatItem as MaterialCardView, format, null)
|
||||
if (selectedVideo == format) formatItem.isChecked = true
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
package com.deniscerri.ytdl.ui.more.settings
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Typeface
|
||||
import android.os.Bundle
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.utils.MDUtil.getStringArray
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.ui.adapter.SortableTextItemAdapter
|
||||
import com.deniscerri.ytdl.util.UiUtil
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
|
||||
class AdvancedSettingsFragment : BaseSettingsFragment() {
|
||||
override val title: Int = R.string.advanced
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.advanced_preferences, rootKey)
|
||||
}
|
||||
}
|
||||
|
|
@ -334,7 +334,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
|||
}
|
||||
|
||||
findPreference<MultiSelectListPreference>("swipe_gesture")?.apply {
|
||||
val s = getString(R.string.preferred_search_engine_summary)
|
||||
val s = getString(R.string.swipe_gestures_summary)
|
||||
if (values.size == entries.size) {
|
||||
summary = "${s}\n[${getString(R.string.all)}]"
|
||||
}else if (values.size > 0) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.deniscerri.ytdl.ui.more.settings.advanced
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.ui.more.settings.BaseSettingsFragment
|
||||
import com.deniscerri.ytdl.util.UiUtil
|
||||
|
||||
|
||||
class AdvancedSettingsFragment : BaseSettingsFragment() {
|
||||
override val title: Int = R.string.advanced
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.advanced_preferences, rootKey)
|
||||
findPreference<Preference>("yt_player_client")?.setOnPreferenceClickListener {
|
||||
findNavController().navigate(R.id.youtubePlayerClientFragment)
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
package com.deniscerri.ytdl.ui.more.settings.advanced
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.AccelerateDecelerateInterpolator
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdl.R
|
||||
import com.deniscerri.ytdl.database.models.Format
|
||||
import com.deniscerri.ytdl.database.models.YoutubePlayerClientItem
|
||||
import com.deniscerri.ytdl.ui.adapter.YoutubePlayerClientAdapter
|
||||
import com.deniscerri.ytdl.ui.more.settings.SettingsActivity
|
||||
import com.deniscerri.ytdl.util.UiUtil
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.common.reflect.TypeToken
|
||||
import com.google.gson.Gson
|
||||
|
||||
|
||||
class YoutubePlayerClientFragment : Fragment(), YoutubePlayerClientAdapter.OnItemClickListener {
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var listAdapter: YoutubePlayerClientAdapter
|
||||
private lateinit var noResults : RelativeLayout
|
||||
private lateinit var settingsActivity: SettingsActivity
|
||||
private lateinit var preferences: SharedPreferences
|
||||
private lateinit var currentList: MutableList<YoutubePlayerClientItem>
|
||||
private lateinit var currentListRaw: String
|
||||
private lateinit var dragHandle: View
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
settingsActivity = activity as SettingsActivity
|
||||
settingsActivity.changeTopAppbarTitle(getString(R.string.player_client))
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
return inflater.inflate(R.layout.fragment_youtube_player_clients, container, false)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
noResults = view.findViewById(R.id.no_results)
|
||||
dragHandle = view.findViewById(R.id.drag)
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(dragDropHelper)
|
||||
listAdapter = YoutubePlayerClientAdapter(this,settingsActivity, itemTouchHelper)
|
||||
recyclerView = view.findViewById(R.id.recycler_view)
|
||||
recyclerView.layoutManager = LinearLayoutManager(context)
|
||||
recyclerView.adapter = listAdapter
|
||||
itemTouchHelper.attachToRecyclerView(recyclerView)
|
||||
currentListRaw = preferences.getString("youtube_player_clients", "[]")!!
|
||||
val itemType = object : TypeToken<List<YoutubePlayerClientItem>>() {}.type
|
||||
currentList = Gson().fromJson<List<YoutubePlayerClientItem>>(currentListRaw, itemType).toMutableList()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
|
||||
val newClient = view.findViewById<Chip>(R.id.newClient)
|
||||
newClient.setOnClickListener {
|
||||
UiUtil.showYoutubePlayerClientSheet(
|
||||
settingsActivity, preferences, null,
|
||||
newValue = { newItem ->
|
||||
currentList.add(newItem)
|
||||
currentListRaw = Gson().toJson(currentList).toString()
|
||||
updateRecords()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
checkNoResults()
|
||||
},
|
||||
deleted = {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
checkNoResults()
|
||||
|
||||
dragHandle.setOnClickListener {
|
||||
listAdapter.toggleShowDragHandle()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRecords() {
|
||||
preferences.edit().putString("youtube_player_clients", currentListRaw).apply()
|
||||
}
|
||||
|
||||
private fun checkNoResults() {
|
||||
val hasNoResults = currentList.isEmpty()
|
||||
noResults.isVisible = hasNoResults
|
||||
recyclerView.isVisible = !hasNoResults
|
||||
dragHandle.isVisible = !hasNoResults
|
||||
}
|
||||
|
||||
|
||||
override fun onItemClick(item: YoutubePlayerClientItem, index: Int) {
|
||||
UiUtil.showYoutubePlayerClientSheet(
|
||||
settingsActivity, preferences, item,
|
||||
newValue = { newItem ->
|
||||
currentList.remove(item)
|
||||
currentList.add(newItem)
|
||||
currentListRaw = Gson().toJson(currentList).toString()
|
||||
updateRecords()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
},
|
||||
deleted = {
|
||||
onDeleteClick(item, index)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onStatusToggle(item: YoutubePlayerClientItem, enabled: Boolean, index: Int) {
|
||||
currentList[currentList.indexOf(item)].enabled = enabled
|
||||
currentListRaw = Gson().toJson(currentList).toString()
|
||||
updateRecords()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
}
|
||||
|
||||
override fun onDeleteClick(item: YoutubePlayerClientItem, index: Int) {
|
||||
UiUtil.showGenericDeleteDialog(requireContext(), item.playerClient) {
|
||||
currentList.remove(item)
|
||||
currentListRaw = Gson().toJson(currentList).toString()
|
||||
updateRecords()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
checkNoResults()
|
||||
}
|
||||
}
|
||||
|
||||
var movedToNewPositionTag = ""
|
||||
private val dragDropHelper: ItemTouchHelper.SimpleCallback =
|
||||
object : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
val fromPosition = viewHolder.bindingAdapterPosition
|
||||
val toPosition = target.bindingAdapterPosition
|
||||
movedToNewPositionTag = target.itemView.tag.toString()
|
||||
listAdapter.notifyItemMoved(fromPosition, toPosition)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
}
|
||||
|
||||
override fun onSelectedChanged(
|
||||
viewHolder: RecyclerView.ViewHolder?,
|
||||
actionState: Int
|
||||
) {
|
||||
super.onSelectedChanged(viewHolder, actionState)
|
||||
if (ItemTouchHelper.ACTION_STATE_DRAG == actionState) {
|
||||
/**
|
||||
* Change alpha, scale and elevation on drag.
|
||||
*/
|
||||
(viewHolder?.itemView as? MaterialCardView)?.also {
|
||||
AnimatorSet().apply {
|
||||
this.duration = 100L
|
||||
this.interpolator = AccelerateDecelerateInterpolator()
|
||||
|
||||
playTogether(
|
||||
UiUtil.getAlphaAnimator(it, 0.7f),
|
||||
UiUtil.getScaleXAnimator(it, 1.02f),
|
||||
UiUtil.getScaleYAnimator(it, 1.02f),
|
||||
UiUtil.getElevationAnimator(it, R.dimen.elevation_6dp)
|
||||
)
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearView(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
/**
|
||||
* Clear alpha, scale and elevation after drag/swipe
|
||||
*/
|
||||
(viewHolder.itemView as? MaterialCardView)?.also {
|
||||
AnimatorSet().apply {
|
||||
this.duration = 100L
|
||||
this.interpolator = AccelerateDecelerateInterpolator()
|
||||
|
||||
playTogether(
|
||||
UiUtil.getAlphaAnimator(it, 1f),
|
||||
UiUtil.getScaleXAnimator(it, 1f),
|
||||
UiUtil.getScaleYAnimator(it, 1f),
|
||||
UiUtil.getElevationAnimator(it, R.dimen.elevation_2dp)
|
||||
)
|
||||
}.start()
|
||||
}
|
||||
|
||||
val currentIndex = currentList.indexOfFirst { it.playerClient == viewHolder.itemView.tag.toString() }
|
||||
val newIndex = currentList.indexOfFirst { it.playerClient == movedToNewPositionTag }
|
||||
|
||||
val newList = mutableListOf<YoutubePlayerClientItem>()
|
||||
|
||||
if (currentIndex != newIndex && currentIndex >= 0 && newIndex >= 0) {
|
||||
Log.e("AAAAAAAAAAAAA", "${currentIndex} ${newIndex}")
|
||||
if(currentIndex > newIndex) {
|
||||
newList.addAll(currentList.subList(0, newIndex))
|
||||
newList.add(currentList[currentIndex])
|
||||
currentList.remove(currentList[currentIndex])
|
||||
newList.addAll(currentList.subList(newIndex, currentList.size))
|
||||
}else{
|
||||
val toMove = currentList[currentIndex]
|
||||
newList.addAll(currentList.subList(0, currentIndex))
|
||||
newList.addAll(currentList.subList(currentIndex + 1, newIndex + 1))
|
||||
newList.add(toMove)
|
||||
newList.addAll(currentList.subList(newIndex + 1, currentList.size))
|
||||
}
|
||||
|
||||
currentList.clear()
|
||||
currentList.addAll(newList)
|
||||
currentListRaw = Gson().toJson(currentList).toString()
|
||||
updateRecords()
|
||||
listAdapter.submitList(currentList.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun isLongPressDragEnabled(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import android.content.SharedPreferences
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.text.format.DateFormat
|
||||
import android.util.DisplayMetrics
|
||||
|
|
@ -46,6 +47,8 @@ import androidx.core.text.HtmlCompat
|
|||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginBottom
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
|
@ -60,6 +63,8 @@ import com.deniscerri.ytdl.database.models.DownloadItem
|
|||
import com.deniscerri.ytdl.database.models.Format
|
||||
import com.deniscerri.ytdl.database.models.HistoryItem
|
||||
import com.deniscerri.ytdl.database.models.TemplateShortcut
|
||||
import com.deniscerri.ytdl.database.models.YoutubePlayerClientItem
|
||||
import com.deniscerri.ytdl.database.models.YoutubePoTokenItem
|
||||
import com.deniscerri.ytdl.database.repository.DownloadRepository
|
||||
import com.deniscerri.ytdl.database.viewmodel.CommandTemplateViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
||||
|
|
@ -86,10 +91,13 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.materialswitch.MaterialSwitch
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.android.material.textfield.TextInputLayout.END_ICON_CUSTOM
|
||||
import com.google.android.material.textfield.TextInputLayout.END_ICON_NONE
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
import com.google.android.material.timepicker.TimeFormat
|
||||
import com.google.gson.Gson
|
||||
import com.yausername.youtubedl_android.YoutubeDL
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -2284,6 +2292,103 @@ object UiUtil {
|
|||
parentView.addView(child)
|
||||
}
|
||||
|
||||
bottomSheet.show()
|
||||
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
bottomSheet.window!!.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
|
||||
fun showYoutubePlayerClientSheet(context: Activity, preferences: SharedPreferences, currentValue: YoutubePlayerClientItem?, newValue: (item: YoutubePlayerClientItem) -> Unit, deleted: () -> Unit){
|
||||
val bottomSheet = BottomSheetDialog(context)
|
||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
bottomSheet.setContentView(R.layout.youtube_player_clients)
|
||||
|
||||
val title : TextInputLayout = bottomSheet.findViewById(R.id.title)!!
|
||||
val chipGroup : ChipGroup = bottomSheet.findViewById(R.id.chipGroup)!!
|
||||
val suggestedLabel : View = bottomSheet.findViewById(R.id.suggestedLabel)!!
|
||||
val okBtn : Button = bottomSheet.findViewById(R.id.client_create)!!
|
||||
val deleteBtn : Button = bottomSheet.findViewById(R.id.client_delete)!!
|
||||
deleteBtn.isVisible = currentValue != null
|
||||
|
||||
val contentLinear : LinearLayout = bottomSheet.findViewById(R.id.contentLinear)!!
|
||||
|
||||
val defaultChips = context.getStringArray(R.array.youtube_player_clients).toMutableSet()
|
||||
|
||||
title.isEndIconVisible = false
|
||||
title.editText!!.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
override fun afterTextChanged(p0: Editable?) {
|
||||
chipGroup.children.forEach { (it as Chip).isChecked = false }
|
||||
chipGroup.children.firstOrNull { (it as Chip).text == p0.toString() }?.apply {
|
||||
(this as Chip).isChecked = true
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val existingConfigsRaw = preferences.getString("youtube_player_clients", "[]")
|
||||
val itemType = object : com.google.common.reflect.TypeToken<List<YoutubePlayerClientItem>>() {}.type
|
||||
val existingConfigs = Gson().fromJson<List<YoutubePlayerClientItem>>(existingConfigsRaw, itemType).toMutableList()
|
||||
|
||||
defaultChips.filter { it.isNotBlank() }.forEach {
|
||||
if (!existingConfigs.any { it2 -> it2.playerClient == it }) {
|
||||
val tmp = context.layoutInflater.inflate(R.layout.filter_chip, chipGroup, false) as Chip
|
||||
tmp.text = it
|
||||
tmp.setOnClickListener {
|
||||
title.editText!!.setText(tmp.text.toString())
|
||||
}
|
||||
chipGroup.addView(tmp)
|
||||
}
|
||||
}
|
||||
|
||||
if (chipGroup.children.count() == 0) {
|
||||
suggestedLabel.isVisible = false
|
||||
}
|
||||
|
||||
val poTokenInputs = contentLinear.children.filter { it is TextInputLayout }.map { it as TextInputLayout }.toList()
|
||||
for(p in poTokenInputs) {
|
||||
p.setEndIconOnClickListener {
|
||||
val clipboard: ClipboardManager = context.getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
p.editText!!.setText(clipboard.primaryClip?.getItemAt(0)?.text)
|
||||
}
|
||||
}
|
||||
|
||||
currentValue?.apply {
|
||||
title.editText!!.setText(this.playerClient)
|
||||
for (t in this.poTokens) {
|
||||
poTokenInputs.firstOrNull { it.tag == "potoken_${t.context}" }?.editText?.setText(t.token)
|
||||
}
|
||||
okBtn.text = context.getString(R.string.edit)
|
||||
}
|
||||
|
||||
okBtn.setOnClickListener {
|
||||
val titleVal = title.editText!!.text.toString()
|
||||
if (titleVal.isBlank()) {
|
||||
title.error = "Player Client tag shouldn't be empty"
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if(existingConfigs.any { it2 -> it2.playerClient == titleVal } && ( currentValue == null || currentValue.playerClient != titleVal )) {
|
||||
title.error = "Player Client is already created"
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
val obj = YoutubePlayerClientItem(titleVal, mutableListOf())
|
||||
poTokenInputs.filter { it.editText!!.text.isNotBlank() && it.tag.toString().startsWith("potoken") }.forEach {
|
||||
obj.poTokens.add(YoutubePoTokenItem(it.tag.toString().split("potoken_")[1], it.editText!!.text.toString()))
|
||||
}
|
||||
bottomSheet.cancel()
|
||||
newValue(obj)
|
||||
}
|
||||
|
||||
deleteBtn.setOnClickListener {
|
||||
bottomSheet.cancel()
|
||||
deleted()
|
||||
}
|
||||
|
||||
|
||||
bottomSheet.show()
|
||||
bottomSheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
bottomSheet.window!!.setLayout(
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.deniscerri.ytdl.database.models.ChapterItem
|
|||
import com.deniscerri.ytdl.database.models.DownloadItem
|
||||
import com.deniscerri.ytdl.database.models.Format
|
||||
import com.deniscerri.ytdl.database.models.ResultItem
|
||||
import com.deniscerri.ytdl.database.models.YoutubePlayerClientItem
|
||||
import com.deniscerri.ytdl.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdl.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdl.util.Extensions.getIntByAny
|
||||
|
|
@ -1237,27 +1238,40 @@ class YTDLPUtil(private val context: Context) {
|
|||
}
|
||||
|
||||
private fun YoutubeDLRequest.setYoutubeExtractorArgs() {
|
||||
val playerClient = sharedPreferences.getString("yt_player_client", "")!!.split(",").filter { it.isNotBlank() }.toMutableList()
|
||||
val extractorArgs = mutableListOf<String>()
|
||||
val playerClients = mutableListOf<String>()
|
||||
val poTokens = mutableListOf<String>()
|
||||
|
||||
val poToken = sharedPreferences.getString("youtube_po_token", "")!!
|
||||
if (poToken.isNotBlank() && !playerClient.contains("web")) {
|
||||
playerClient.add("web")
|
||||
val configuredPlayerClientsRaw = sharedPreferences.getString("youtube_player_clients", "[]")!!
|
||||
val itemType = object : com.google.common.reflect.TypeToken<List<YoutubePlayerClientItem>>() {}.type
|
||||
val configuredPlayerClients = Gson().fromJson<List<YoutubePlayerClientItem>>(configuredPlayerClientsRaw, itemType).toMutableList()
|
||||
|
||||
for (value in configuredPlayerClients) {
|
||||
if (value.enabled) {
|
||||
playerClients.add(value.playerClient)
|
||||
value.poTokens.forEach { pt ->
|
||||
poTokens.add("${value.playerClient}.${pt.context}+${pt.token}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (playerClient.isNotEmpty()){
|
||||
extractorArgs.add("player_client=${playerClient.joinToString(",")}")
|
||||
if (playerClients.isNotEmpty()){
|
||||
extractorArgs.add("player_client=${playerClients.joinToString(",")}")
|
||||
}
|
||||
|
||||
val lang = Locale.getDefault().language
|
||||
val langTag = Locale.getDefault().toLanguageTag()
|
||||
if (context.getStringArray(R.array.subtitle_langs).contains(lang)) {
|
||||
extractorArgs.add("lang=$lang")
|
||||
}else if (context.getStringArray(R.array.subtitle_langs).contains(langTag)) {
|
||||
extractorArgs.add("lang=$langTag")
|
||||
if (poTokens.isNotEmpty()) {
|
||||
extractorArgs.add("po_token=${poTokens.joinToString(",")}")
|
||||
}
|
||||
if (poToken.isNotBlank()) {
|
||||
extractorArgs.add("po_token=web+$poToken")
|
||||
|
||||
val useLanguageForMetadata = sharedPreferences.getBoolean("use_app_language_for_metadata", true)
|
||||
if (useLanguageForMetadata) {
|
||||
val lang = Locale.getDefault().language
|
||||
val langTag = Locale.getDefault().toLanguageTag()
|
||||
if (context.getStringArray(R.array.subtitle_langs).contains(lang)) {
|
||||
extractorArgs.add("lang=$lang")
|
||||
}else if (context.getStringArray(R.array.subtitle_langs).contains(langTag)) {
|
||||
extractorArgs.add("lang=$langTag")
|
||||
}
|
||||
}
|
||||
|
||||
val otherArgs = sharedPreferences.getString("youtube_other_extractor_args", "")!!
|
||||
|
|
|
|||
5
app/src/main/res/drawable/baseline_person_24.xml
Normal file
5
app/src/main/res/drawable/baseline_person_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="?android:colorAccent" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||
|
||||
</vector>
|
||||
|
|
@ -110,8 +110,9 @@
|
|||
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||
app:layout_constraintEnd_toStartOf="@+id/active_pause_cancel_btns"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview">
|
||||
app:layout_constraintTop_toTopOf="@+id/active_pause_cancel_btns">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
|
|
@ -120,7 +121,6 @@
|
|||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowDx="2"
|
||||
|
|
@ -200,8 +200,6 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/output"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -222,7 +220,6 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/format_source_linear"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -103,5 +102,54 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/format_layout_linear"
|
||||
android:layout_width="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/layout"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/layout_list"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingVertical="10dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:drawablePadding="30dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/list"
|
||||
app:drawableStartCompat="@drawable/ic_check" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/layout_grid"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingVertical="10dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:drawablePadding="30dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/grid"
|
||||
app:drawableStartCompat="@drawable/empty" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@
|
|||
<TextView
|
||||
android:id="@+id/container"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorPrimaryInverse"
|
||||
android:textColor="@color/white"
|
||||
android:clickable="false"
|
||||
android:layout_height="55dp"
|
||||
app:layout_constraintDimensionRatio="H,1:1"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
app:cornerRadius="10dp"
|
||||
|
|
|
|||
171
app/src/main/res/layout/format_item_grid.xml
Normal file
171
app/src/main/res/layout/format_item_grid.xml
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/format_card_constraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:checkable="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
app:checkedIcon="@null"
|
||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardPreventCornerOverlap="true"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:paddingVertical="5dp"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/container"
|
||||
android:layout_width="50dp"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorPrimaryInverse"
|
||||
android:textColor="@color/white"
|
||||
android:clickable="false"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="H,1:1"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/format_loading_progress"
|
||||
android:visibility="gone"
|
||||
android:layout_width="0dp"
|
||||
android:indeterminate="true"
|
||||
app:trackColor="#000"
|
||||
android:layout_gravity="bottom"
|
||||
android:alpha="0.3"
|
||||
android:scaleY="200"
|
||||
app:layout_constraintTop_toTopOf="@id/container"
|
||||
app:layout_constraintBottom_toBottomOf="@id/container"
|
||||
app:layout_constraintStart_toStartOf="@id/container"
|
||||
app:layout_constraintEnd_toEndOf="@id/container"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/format_note"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="top"
|
||||
android:maxLines="2"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textDirection="locale"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/container"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/audio_formats"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Primary"
|
||||
android:layout_width="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="5dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorPrimary"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:drawableStartCompat="@drawable/ic_music_formatcard"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/container"
|
||||
app:layout_constraintTop_toBottomOf="@+id/format_note" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/barrier"
|
||||
app:barrierDirection="bottom"
|
||||
app:constraint_referenced_ids="container, audio_formats" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:chipSpacingHorizontal="0dp"
|
||||
app:chipSpacingVertical="5dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/container">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/format_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/backgroundColor"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/codec"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/file_size"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Tertiary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="@drawable/rounded_corner"
|
||||
android:backgroundTint="?attr/colorSecondary"
|
||||
android:clickable="false"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
|
@ -134,11 +134,12 @@
|
|||
android:paddingVertical="20dp"
|
||||
android:text="@string/video" />
|
||||
|
||||
<LinearLayout
|
||||
<GridLayout
|
||||
android:id="@+id/video_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
android:columnCount="1"
|
||||
android:alignmentMode="alignBounds"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -160,11 +161,12 @@
|
|||
android:paddingVertical="20dp"
|
||||
android:text="@string/audio" />
|
||||
|
||||
<LinearLayout
|
||||
<GridLayout
|
||||
android:id="@+id/audio_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
android:columnCount="1"
|
||||
android:alignmentMode="alignBounds"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
57
app/src/main/res/layout/fragment_youtube_player_clients.xml
Normal file
57
app/src/main/res/layout/fragment_youtube_player_clients.xml
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.deniscerri.ytdl.ui.more.terminal.TerminalActivity">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/newClient"
|
||||
style="@style/Widget.Material3.Chip.Assist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:text="@string/add"
|
||||
app:chipIcon="@drawable/ic_plus" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drag"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:padding="10dp"
|
||||
app:drawableStartCompat="@drawable/ic_drag_handle"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/newClient"
|
||||
android:layout_alignParentBottom="true" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<include layout="@layout/no_results"
|
||||
android:visibility="gone"/>
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
74
app/src/main/res/layout/player_client_item.xml
Normal file
74
app/src/main/res/layout/player_client_item.xml
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/card"
|
||||
android:layout_width="match_parent"
|
||||
android:checkable="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:backgroundTint="@android:color/transparent"
|
||||
app:checkedIcon="@null"
|
||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardPreventCornerOverlap="true"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingHorizontal="15dp"
|
||||
android:paddingTop="15dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/drag_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:paddingVertical="16dp"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:visibility="gone"
|
||||
android:tintMode="src_in"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_drag_handle"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginEnd="20dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginEnd="20dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/materialSwitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
179
app/src/main/res/layout/youtube_player_clients.xml
Normal file
179
app/src/main/res/layout/youtube_player_clients.xml
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="20dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/player_client"
|
||||
android:textSize="25sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="YouTube"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/client_delete"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:outlineProvider="none"
|
||||
app:icon="@drawable/baseline_delete_24"
|
||||
android:contentDescription="@string/Remove"
|
||||
app:layout_constraintBottom_toBottomOf="@id/client_create"
|
||||
app:layout_constraintEnd_toStartOf="@+id/client_create"
|
||||
app:layout_constraintTop_toTopOf="@id/client_create" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/client_create"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="all"
|
||||
android:text="@string/create"
|
||||
app:icon="@drawable/ic_check"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/contentLinear"
|
||||
android:padding="15dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/title"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/title"
|
||||
android:tag="title"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/suggestedLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/suggested" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="10dp"
|
||||
android:scrollbars="none"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/chipGroup"
|
||||
android:layout_width="wrap_content"
|
||||
app:chipSpacingVertical="-10dp"
|
||||
app:singleSelection="true"
|
||||
app:chipSpacing="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleLine="true">
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/poTokenLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:text="PO Token"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/po_token_gvs"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="potoken_gvs"
|
||||
android:hint="PO Token (GVS)"
|
||||
app:endIconDrawable="@drawable/ic_clipboard"
|
||||
app:endIconMode="custom"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/po_token_player"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:tag="potoken_player"
|
||||
android:hint="PO Token (Player)"
|
||||
app:endIconDrawable="@drawable/ic_clipboard"
|
||||
app:endIconMode="custom"
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -47,6 +47,14 @@
|
|||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/advancedSettingsFragment"
|
||||
android:name="com.deniscerri.ytdl.ui.more.settings.AdvancedSettingsFragment"
|
||||
android:label="AdvancedSettingsFragment" />
|
||||
android:name="com.deniscerri.ytdl.ui.more.settings.advanced.AdvancedSettingsFragment"
|
||||
android:label="AdvancedSettingsFragment" >
|
||||
<action
|
||||
android:id="@+id/action_advancedSettingsFragment_to_youtubePlayerClientFragment"
|
||||
app:destination="@id/youtubePlayerClientFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/youtubePlayerClientFragment"
|
||||
android:name="com.deniscerri.ytdl.ui.more.settings.advanced.YoutubePlayerClientFragment"
|
||||
android:label="YoutubePlayerClientFragment" />
|
||||
</navigation>
|
||||
|
|
@ -1527,4 +1527,18 @@
|
|||
<item>NEWPIPE</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="youtube_player_clients">
|
||||
<item>android</item>
|
||||
<item>ios</item>
|
||||
<item>web</item>
|
||||
<item>mweb</item>
|
||||
<item>android_vr</item>
|
||||
<item>web_safari</item>
|
||||
<item>web_embedded</item>
|
||||
<item>tv</item>
|
||||
<item>tv_embedded</item>
|
||||
<item>default</item>
|
||||
<item>all</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
|
|
@ -451,4 +451,10 @@
|
|||
<string name="minutes">Minutes</string>
|
||||
<string name="prefer_container_over_codec_audio">Prefer Container over Codec For Audio Downloads</string>
|
||||
<string name="prefer_container_over_codec_audio_summary">With this enabled, the preferred audio codec preference will be ignored and only container will change</string>
|
||||
<string name="player_client">Player Client</string>
|
||||
<string name="player_client_summary"><![CDATA[YouTube Player Clients & PO Token]]></string>
|
||||
<string name="use_app_language_for_metadata">Use App Language for Metadata</string>
|
||||
<string name="layout">Layout</string>
|
||||
<string name="list">List</string>
|
||||
<string name="grid">Grid</string>
|
||||
</resources>
|
||||
|
|
@ -3,19 +3,19 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<PreferenceCategory android:title="YouTube">
|
||||
<EditTextPreference
|
||||
<Preference
|
||||
android:defaultValue=""
|
||||
android:icon="@drawable/ic_code"
|
||||
android:icon="@drawable/baseline_person_24"
|
||||
android:key="yt_player_client"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="Player Client" />
|
||||
android:summary="@string/player_client_summary"
|
||||
android:title="@string/player_client" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue=""
|
||||
android:icon="@drawable/ic_code"
|
||||
android:key="youtube_po_token"
|
||||
app:useSimpleSummaryProvider="true"
|
||||
android:title="PO Token [Web]" />
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
android:icon="@drawable/ic_language"
|
||||
android:defaultValue="true"
|
||||
android:key="use_app_language_for_metadata"
|
||||
android:title="@string/use_app_language_for_metadata" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue=""
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
<PreferenceCategory android:title="@string/command_templates">
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
android:icon="@drawable/ic_terminal"
|
||||
android:key="enable_data_fetching_extra_commands"
|
||||
android:summary="@string/data_fetching_extra_command_summary"
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
|
||||
<PreferenceCategory android:title="@string/downloading" android:enabled="false">
|
||||
<SwitchPreferenceCompat
|
||||
android:widgetLayout="@layout/preferece_material_switch"
|
||||
android:icon="@drawable/if_file_rename"
|
||||
android:key="disable_write_info_json"
|
||||
android:summary="@string/disable_write_info_json_summary"
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ buildscript {
|
|||
retrofitVer = "2.9.0"
|
||||
kodeinVer = "7.16.0"
|
||||
navVer = "2.8.3"
|
||||
media3_version = "1.4.1"
|
||||
media3_version = "1.5.1"
|
||||
agp_version = '8.1.0'
|
||||
agp_version1 = '7.4.2'
|
||||
roomVer = '2.5.2'
|
||||
|
|
|
|||
Loading…
Reference in a new issue