more features & u can change cache folder now
This commit is contained in:
parent
60b42a0751
commit
a5438eaff3
14 changed files with 263 additions and 111 deletions
|
|
@ -159,7 +159,7 @@ dependencies {
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$navVer"
|
implementation "androidx.navigation:navigation-ui-ktx:$navVer"
|
||||||
implementation 'androidx.core:core-ktx:1.15.0'
|
implementation 'androidx.core:core-ktx:1.15.0'
|
||||||
implementation 'androidx.test.ext:junit-ktx:1.2.1'
|
implementation 'androidx.test.ext:junit-ktx:1.2.1'
|
||||||
implementation 'androidx.compose.ui:ui-android:1.7.6'
|
implementation 'androidx.compose.ui:ui-android:1.7.7'
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||||
testImplementation "junit:junit:$junitVer"
|
testImplementation "junit:junit:$junitVer"
|
||||||
androidTestImplementation "junit:junit:$junitVer"
|
androidTestImplementation "junit:junit:$junitVer"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ package com.deniscerri.ytdl.database.models
|
||||||
data class YoutubePlayerClientItem(
|
data class YoutubePlayerClientItem(
|
||||||
var playerClient: String,
|
var playerClient: String,
|
||||||
var poTokens: MutableList<YoutubePoTokenItem>,
|
var poTokens: MutableList<YoutubePoTokenItem>,
|
||||||
var enabled: Boolean = true
|
var enabled: Boolean = true,
|
||||||
|
var useOnlyPoToken: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
data class YoutubePoTokenItem(
|
data class YoutubePoTokenItem(
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.Window
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
|
|
@ -36,6 +37,9 @@ import com.deniscerri.ytdl.util.Extensions.enableTextHighlight
|
||||||
import com.deniscerri.ytdl.util.FileUtil
|
import com.deniscerri.ytdl.util.FileUtil
|
||||||
import com.deniscerri.ytdl.util.UiUtil
|
import com.deniscerri.ytdl.util.UiUtil
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
|
@ -45,7 +49,6 @@ import com.google.android.material.textfield.TextInputLayout
|
||||||
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
import it.xabaras.android.recyclerview.swipedecorator.RecyclerViewSwipeDecorator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,7 +121,7 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
||||||
private fun initChips() {
|
private fun initChips() {
|
||||||
val new = view?.findViewById<Chip>(R.id.newCookie)
|
val new = view?.findViewById<Chip>(R.id.newCookie)
|
||||||
new?.setOnClickListener {
|
new?.setOnClickListener {
|
||||||
showDialog(null)
|
showBottomSheet(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,17 +175,17 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDialog(item: CookieItem?){
|
private fun showBottomSheet(item: CookieItem?){
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
val layout = BottomSheetDialog(requireContext())
|
||||||
builder.setTitle(getString(R.string.cookies))
|
layout.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
val layout = layoutInflater.inflate(R.layout.cookie_details, null)
|
layout.setContentView(R.layout.cookie_bottom_sheet)
|
||||||
val editText = layout.findViewById<EditText>(R.id.url_edittext)
|
|
||||||
layout.findViewById<TextInputLayout>(R.id.url_textinput).hint = "URL"
|
val editText = layout.findViewById<EditText>(R.id.url_edittext)!!
|
||||||
val text = item?.url ?: "https://"
|
val text = item?.url ?: "https://"
|
||||||
editText.setText(text)
|
editText.setText(text)
|
||||||
editText.setSelection(editText.text.length)
|
editText.setSelection(editText.text.length)
|
||||||
val current = layout.findViewById<MaterialCardView>(R.id.current)
|
val current = layout.findViewById<MaterialCardView>(R.id.current)!!
|
||||||
current.isVisible = item != null
|
current.isVisible = item != null
|
||||||
item?.apply {
|
item?.apply {
|
||||||
current.findViewById<TextView>(R.id.currentText).apply {
|
current.findViewById<TextView>(R.id.currentText).apply {
|
||||||
|
|
@ -190,45 +193,51 @@ class CookiesFragment : Fragment(), CookieAdapter.OnItemClickListener {
|
||||||
enableTextHighlight()
|
enableTextHighlight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setView(layout)
|
|
||||||
|
|
||||||
item?.apply {
|
val clipboard = layout.findViewById<MaterialButton>(R.id.clipboard)!!
|
||||||
builder.setNeutralButton(
|
clipboard.isVisible = item != null
|
||||||
getString(android.R.string.copy)
|
|
||||||
) { dialog: DialogInterface?, which: Int ->
|
|
||||||
UiUtil.copyToClipboard(cookiesViewModel.cookieHeader + "\n" + item.content, requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setPositiveButton(
|
val getCookies = layout.findViewById<MaterialButton>(R.id.getCookiesBtn)!!
|
||||||
if (item == null) getString(R.string.get_cookies) else getString(R.string.update)
|
getCookies.setOnClickListener {
|
||||||
) { dialog: DialogInterface?, which: Int ->
|
|
||||||
val myIntent = Intent(requireContext(), WebViewActivity::class.java)
|
val myIntent = Intent(requireContext(), WebViewActivity::class.java)
|
||||||
myIntent.putExtra("url", editText.text.toString())
|
myIntent.putExtra("url", editText.text.toString())
|
||||||
|
layout.dismiss()
|
||||||
startActivity(myIntent)
|
startActivity(myIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the negative button of the alert dialog
|
item?.apply {
|
||||||
builder.setNegativeButton(
|
clipboard.setOnClickListener {
|
||||||
getString(R.string.cancel)
|
UiUtil.copyToClipboard(cookiesViewModel.cookieHeader + "\n" + item.content, requireActivity())
|
||||||
) { dialog: DialogInterface?, which: Int -> }
|
layout.dismiss()
|
||||||
val dialog = builder.create()
|
}
|
||||||
editText.doOnTextChanged { text, start, before, count ->
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
getCookies.text = getString(R.string.update)
|
||||||
}
|
}
|
||||||
dialog.show()
|
|
||||||
|
editText.doOnTextChanged { text, start, before, count ->
|
||||||
|
getCookies.isEnabled = editText.text.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
val imm = mainActivity.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = mainActivity.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
editText!!.postDelayed({
|
editText.postDelayed({
|
||||||
editText.requestFocus()
|
editText.requestFocus()
|
||||||
imm.showSoftInput(editText, 0)
|
imm.showSoftInput(editText, 0)
|
||||||
}, 300)
|
}, 300)
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
|
||||||
|
layout.show()
|
||||||
|
layout.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
layout.window!!.setLayout(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
|
||||||
|
getCookies.isEnabled = editText.text.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(cookie: CookieItem) {
|
override fun onItemClick(cookie: CookieItem) {
|
||||||
showDialog(cookie)
|
showBottomSheet(cookie)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSelected(cookie: CookieItem) {
|
override fun onSelected(cookie: CookieItem) {
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
private var musicPath: Preference? = null
|
private var musicPath: Preference? = null
|
||||||
private var videoPath: Preference? = null
|
private var videoPath: Preference? = null
|
||||||
private var commandPath: Preference? = null
|
private var commandPath: Preference? = null
|
||||||
|
private var cachePath: Preference? = null
|
||||||
private var accessAllFiles : Preference? = null
|
private var accessAllFiles : Preference? = null
|
||||||
private var noFragments: SwitchPreferenceCompat? = null
|
private var noFragments: SwitchPreferenceCompat? = null
|
||||||
private var keepFragments: SwitchPreferenceCompat? = null
|
private var keepFragments: SwitchPreferenceCompat? = null
|
||||||
|
|
@ -62,6 +63,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
musicPath = findPreference("music_path")
|
musicPath = findPreference("music_path")
|
||||||
videoPath = findPreference("video_path")
|
videoPath = findPreference("video_path")
|
||||||
commandPath = findPreference("command_path")
|
commandPath = findPreference("command_path")
|
||||||
|
cachePath = findPreference("cache_path")
|
||||||
accessAllFiles = findPreference("access_all_files")
|
accessAllFiles = findPreference("access_all_files")
|
||||||
noFragments = findPreference("no_part")
|
noFragments = findPreference("no_part")
|
||||||
keepFragments = findPreference("keep_cache")
|
keepFragments = findPreference("keep_cache")
|
||||||
|
|
@ -80,6 +82,9 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
if (preferences.getString("command_path", "")!!.isEmpty()) {
|
if (preferences.getString("command_path", "")!!.isEmpty()) {
|
||||||
editor.putString("command_path", FileUtil.getDefaultCommandPath())
|
editor.putString("command_path", FileUtil.getDefaultCommandPath())
|
||||||
}
|
}
|
||||||
|
if (preferences.getString("cache_path", "")!!.isEmpty()) {
|
||||||
|
editor.putString("cache_path", FileUtil.getCachePath(requireContext()))
|
||||||
|
}
|
||||||
|
|
||||||
if (FileUtil.hasAllFilesAccess()) {
|
if (FileUtil.hasAllFilesAccess()) {
|
||||||
accessAllFiles!!.isVisible = false
|
accessAllFiles!!.isVisible = false
|
||||||
|
|
@ -119,6 +124,20 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
commandPathResultLauncher.launch(intent)
|
commandPathResultLauncher.launch(intent)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachePath!!.summary = FileUtil.formatPath(preferences.getString("cache_path", "")!!)
|
||||||
|
cachePath!!.onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
UiUtil.showGenericConfirmDialog(requireContext(), getString(R.string.cache_directory), getString(R.string.cache_directory_warning)) {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||||
|
cachePathResultLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
if(VERSION.SDK_INT >= 30){
|
if(VERSION.SDK_INT >= 30){
|
||||||
accessAllFiles!!.onPreferenceClickListener =
|
accessAllFiles!!.onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
|
|
@ -271,6 +290,20 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
changePath(commandPath, result.data, COMMAND_PATH_CODE)
|
changePath(commandPath, result.data, COMMAND_PATH_CODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var cachePathResultLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
result.data?.data?.let {
|
||||||
|
activity?.contentResolver?.takePersistableUriPermission(
|
||||||
|
it,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
changePath(cachePath, result.data, CACHE_PATH_CODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
||||||
val path = data!!.data.toString()
|
val path = data!!.data.toString()
|
||||||
|
|
@ -281,6 +314,7 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
MUSIC_PATH_CODE -> editor.putString("music_path", path)
|
MUSIC_PATH_CODE -> editor.putString("music_path", path)
|
||||||
VIDEO_PATH_CODE -> editor.putString("video_path", path)
|
VIDEO_PATH_CODE -> editor.putString("video_path", path)
|
||||||
COMMAND_PATH_CODE -> editor.putString("command_path", path)
|
COMMAND_PATH_CODE -> editor.putString("command_path", path)
|
||||||
|
CACHE_PATH_CODE -> editor.putString("cache_path", path)
|
||||||
}
|
}
|
||||||
editor.apply()
|
editor.apply()
|
||||||
}
|
}
|
||||||
|
|
@ -289,5 +323,6 @@ class FolderSettingsFragment : BaseSettingsFragment() {
|
||||||
const val MUSIC_PATH_CODE = 33333
|
const val MUSIC_PATH_CODE = 33333
|
||||||
const val VIDEO_PATH_CODE = 55555
|
const val VIDEO_PATH_CODE = 55555
|
||||||
const val COMMAND_PATH_CODE = 77777
|
const val COMMAND_PATH_CODE = 77777
|
||||||
|
const val CACHE_PATH_CODE = 99999
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ import androidx.core.content.FileProvider
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.anggrayudi.storage.callback.FileCallback
|
import com.anggrayudi.storage.callback.FileCallback
|
||||||
import com.anggrayudi.storage.callback.FolderCallback
|
import com.anggrayudi.storage.callback.FolderCallback
|
||||||
|
|
@ -39,6 +40,7 @@ import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.internal.closeQuietly
|
import okhttp3.internal.closeQuietly
|
||||||
|
import okhttp3.internal.format
|
||||||
import okhttp3.internal.lowercase
|
import okhttp3.internal.lowercase
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
|
|
@ -283,11 +285,16 @@ object FileUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCachePath(context: Context) : String {
|
fun getCachePath(context: Context) : String {
|
||||||
val externalPath = context.getExternalFilesDir(null)
|
val preference = PreferenceManager.getDefaultSharedPreferences(context).getString("cache_path", "")!!
|
||||||
return if (externalPath == null){
|
if (preference.isEmpty() || !File(formatPath(preference)).canWrite()) {
|
||||||
context.cacheDir.absolutePath + "/downloads/"
|
val externalPath = context.getExternalFilesDir(null)
|
||||||
}else{
|
return if (externalPath == null){
|
||||||
externalPath.absolutePath + "/downloads/"
|
context.cacheDir.absolutePath + "/downloads/"
|
||||||
|
}else{
|
||||||
|
externalPath.absolutePath + "/downloads/"
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
return formatPath(preference)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1761,6 +1761,17 @@ object UiUtil {
|
||||||
deleteDialog.show()
|
deleteDialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showGenericConfirmDialog(context: Context, title: String, content:String, accepted: () -> Unit){
|
||||||
|
val deleteDialog = MaterialAlertDialogBuilder(context)
|
||||||
|
deleteDialog.setTitle(title)
|
||||||
|
deleteDialog.setMessage(content)
|
||||||
|
deleteDialog.setNegativeButton(context.getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
deleteDialog.setPositiveButton(context.getString(R.string.continue_anyway)) { _: DialogInterface?, _: Int ->
|
||||||
|
accepted()
|
||||||
|
}
|
||||||
|
deleteDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
fun showGenericDeleteAllDialog(context: Context, accepted: () -> Unit){
|
fun showGenericDeleteAllDialog(context: Context, accepted: () -> Unit){
|
||||||
val deleteDialog = MaterialAlertDialogBuilder(context)
|
val deleteDialog = MaterialAlertDialogBuilder(context)
|
||||||
deleteDialog.setTitle(context.getString(R.string.you_are_going_to_delete_multiple_items))
|
deleteDialog.setTitle(context.getString(R.string.you_are_going_to_delete_multiple_items))
|
||||||
|
|
@ -2312,6 +2323,9 @@ object UiUtil {
|
||||||
val deleteBtn : Button = bottomSheet.findViewById(R.id.client_delete)!!
|
val deleteBtn : Button = bottomSheet.findViewById(R.id.client_delete)!!
|
||||||
deleteBtn.isVisible = currentValue != null
|
deleteBtn.isVisible = currentValue != null
|
||||||
|
|
||||||
|
val useOnlyPOToken : MaterialSwitch = bottomSheet.findViewById(R.id.use_only_po_token)!!
|
||||||
|
useOnlyPOToken.isChecked = currentValue?.useOnlyPoToken ?: false
|
||||||
|
|
||||||
val contentLinear : LinearLayout = bottomSheet.findViewById(R.id.contentLinear)!!
|
val contentLinear : LinearLayout = bottomSheet.findViewById(R.id.contentLinear)!!
|
||||||
|
|
||||||
val defaultChips = context.getStringArray(R.array.youtube_player_clients).toMutableSet()
|
val defaultChips = context.getStringArray(R.array.youtube_player_clients).toMutableSet()
|
||||||
|
|
@ -2374,7 +2388,12 @@ object UiUtil {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
val obj = YoutubePlayerClientItem(titleVal, mutableListOf())
|
if (useOnlyPOToken.isChecked && (poTokenInputs.filter { it.tag.toString().startsWith("potoken") }.all { it.editText!!.text.isBlank() })) {
|
||||||
|
poTokenInputs.first().error = "You need to write at least one PO Token"
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
val obj = YoutubePlayerClientItem(titleVal, mutableListOf(), true, useOnlyPOToken.isChecked)
|
||||||
poTokenInputs.filter { it.editText!!.text.isNotBlank() && it.tag.toString().startsWith("potoken") }.forEach {
|
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()))
|
obj.poTokens.add(YoutubePoTokenItem(it.tag.toString().split("potoken_")[1], it.editText!!.text.toString()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,9 @@ class YTDLPUtil(private val context: Context) {
|
||||||
request.addOption("--print", "formats")
|
request.addOption("--print", "formats")
|
||||||
request.addOption("-a", urlsFile.absolutePath)
|
request.addOption("-a", urlsFile.absolutePath)
|
||||||
request.applyDefaultOptionsForFetchingData()
|
request.applyDefaultOptionsForFetchingData()
|
||||||
|
if (urls.all { it.isYoutubeURL() }) {
|
||||||
|
request.setYoutubeExtractorArgs()
|
||||||
|
}
|
||||||
|
|
||||||
val txt = parseYTDLRequestString(request)
|
val txt = parseYTDLRequestString(request)
|
||||||
println(txt)
|
println(txt)
|
||||||
|
|
@ -413,6 +416,9 @@ class YTDLPUtil(private val context: Context) {
|
||||||
request.addOption("--print", "%(formats)s")
|
request.addOption("--print", "%(formats)s")
|
||||||
request.addOption("--print", "%(duration)s")
|
request.addOption("--print", "%(duration)s")
|
||||||
request.applyDefaultOptionsForFetchingData()
|
request.applyDefaultOptionsForFetchingData()
|
||||||
|
if (url.isYoutubeURL()) {
|
||||||
|
request.setYoutubeExtractorArgs()
|
||||||
|
}
|
||||||
|
|
||||||
val res = YoutubeDL.getInstance().execute(request)
|
val res = YoutubeDL.getInstance().execute(request)
|
||||||
val results: Array<String?> = try {
|
val results: Array<String?> = try {
|
||||||
|
|
@ -495,6 +501,9 @@ class YTDLPUtil(private val context: Context) {
|
||||||
request.addOption("--get-url")
|
request.addOption("--get-url")
|
||||||
request.addOption("--print", "%(.{urls,chapters})s")
|
request.addOption("--print", "%(.{urls,chapters})s")
|
||||||
request.applyDefaultOptionsForFetchingData()
|
request.applyDefaultOptionsForFetchingData()
|
||||||
|
if (url.isYoutubeURL()) {
|
||||||
|
request.setYoutubeExtractorArgs()
|
||||||
|
}
|
||||||
|
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
||||||
val json = JSONObject(youtubeDLResponse.out)
|
val json = JSONObject(youtubeDLResponse.out)
|
||||||
|
|
@ -1245,7 +1254,10 @@ class YTDLPUtil(private val context: Context) {
|
||||||
|
|
||||||
for (value in configuredPlayerClients) {
|
for (value in configuredPlayerClients) {
|
||||||
if (value.enabled) {
|
if (value.enabled) {
|
||||||
playerClients.add(value.playerClient)
|
if (!value.useOnlyPoToken) {
|
||||||
|
playerClients.add(value.playerClient)
|
||||||
|
}
|
||||||
|
|
||||||
value.poTokens.forEach { pt ->
|
value.poTokens.forEach { pt ->
|
||||||
poTokens.add("${value.playerClient}.${pt.context}+${pt.token}")
|
poTokens.add("${value.playerClient}.${pt.context}+${pt.token}")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/baseline_help_24.xml
Normal file
5
app/src/main/res/drawable/baseline_help_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" 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,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
117
app/src/main/res/layout/cookie_bottom_sheet.xml
Normal file
117
app/src/main/res/layout/cookie_bottom_sheet.xml
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fillViewport="true">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/scr"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:paddingTop="20dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/current"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="20dp"
|
||||||
|
android:layout_marginVertical="5dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/cookies"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:id="@+id/currentText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="20dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:hint="@string/url"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/scr">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/url_edittext"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="2000" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/clipboard"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:icon="@drawable/ic_copy"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/getCookiesBtn"
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="all"
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
android:text="@string/get_cookies"
|
||||||
|
app:icon="@drawable/baseline_cookie_24"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
<?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:padding="10dp"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
|
||||||
android:id="@+id/current"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="10dp"
|
|
||||||
android:layout_marginVertical="5dp"
|
|
||||||
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:orientation="vertical"
|
|
||||||
android:padding="10dp">
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintHeight_max="300dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/currentText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textSize="14sp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/url_textinput"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="10dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/current">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/url_edittext"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="text" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
<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"
|
||||||
android:paddingHorizontal="15dp"
|
android:padding="15dp">
|
||||||
android:paddingTop="15dp">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/drag_view"
|
android:id="@+id/drag_view"
|
||||||
|
|
@ -43,7 +42,7 @@
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="15sp"
|
android:textSize="17sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
||||||
|
|
@ -56,7 +55,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="3"
|
android:maxLines="3"
|
||||||
android:textSize="12sp"
|
android:textSize="14sp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
app:layout_constraintEnd_toStartOf="@+id/materialSwitch"
|
||||||
app:layout_constraintStart_toEndOf="@id/drag_view"
|
app:layout_constraintStart_toEndOf="@id/drag_view"
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,12 @@
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/use_only_po_token"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/use_only_po_token"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -457,4 +457,7 @@
|
||||||
<string name="layout">Layout</string>
|
<string name="layout">Layout</string>
|
||||||
<string name="list">List</string>
|
<string name="list">List</string>
|
||||||
<string name="grid">Grid</string>
|
<string name="grid">Grid</string>
|
||||||
|
<string name="use_only_po_token">Use only PO Token (Ignore Player Client)</string>
|
||||||
|
<string name="cache_directory">Cache Folder</string>
|
||||||
|
<string name="cache_directory_warning">Changing the Cache Folder might cause unexpected issues. If the app cannot write to the configured path, it will resort to the default internal cache directory</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -20,6 +20,12 @@
|
||||||
app:key="command_path"
|
app:key="command_path"
|
||||||
app:title="@string/command_directory" />
|
app:title="@string/command_directory" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:defaultValue=""
|
||||||
|
app:icon="@drawable/baseline_folder_24"
|
||||||
|
app:key="cache_path"
|
||||||
|
app:title="@string/cache_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_access_folder"
|
app:icon="@drawable/ic_access_folder"
|
||||||
app:key="access_all_files"
|
app:key="access_all_files"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue