alot of stuff
added remux-video for audio made copy url similar to history card fixed padding on cards fixed configured download sheet not scrolling implemented chapter suggestions in cuts
This commit is contained in:
parent
9f0d8ab727
commit
f396787b65
27 changed files with 383 additions and 181 deletions
|
|
@ -22,7 +22,7 @@ android {
|
||||||
keyPassword properties["signingConfig.keyPassword"]
|
keyPassword properties["signingConfig.keyPassword"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileSdkVersion "android-UpsideDownCake"
|
compileSdkVersion 33
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.deniscerri.ytdl"
|
applicationId "com.deniscerri.ytdl"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
|
|
@ -119,7 +119,7 @@ dependencies {
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$appCompatVer"
|
implementation "androidx.appcompat:appcompat:$appCompatVer"
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
implementation 'com.google.android.material:material:1.10.0-alpha01'
|
implementation 'com.google.android.material:material:1.9.0-beta01'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.core:core:1.9.0'
|
implementation 'androidx.core:core:1.9.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.3.0'
|
implementation 'androidx.recyclerview:recyclerview:1.3.0'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
|
data class ChapterItem(
|
||||||
|
var start_time: Long,
|
||||||
|
var end_time: Long,
|
||||||
|
var title: String,
|
||||||
|
)
|
||||||
|
|
@ -4,16 +4,20 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.content.Context.CLIPBOARD_SERVICE
|
import android.content.Context.CLIPBOARD_SERVICE
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.text.InputType
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.View.*
|
import android.view.View.*
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.text.TextUtilsCompat
|
import androidx.core.text.TextUtilsCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
|
|
@ -42,6 +46,7 @@ import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.chip.ChipGroup
|
import com.google.android.material.chip.ChipGroup
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
import com.google.android.material.search.SearchBar
|
import com.google.android.material.search.SearchBar
|
||||||
|
|
@ -350,6 +355,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
if (present == null) {
|
if (present == null) {
|
||||||
val chip = layoutinflater!!.inflate(R.layout.input_chip, queriesChipGroup, false) as Chip
|
val chip = layoutinflater!!.inflate(R.layout.input_chip, queriesChipGroup, false) as Chip
|
||||||
chip.text = searchView.editText.text
|
chip.text = searchView.editText.text
|
||||||
|
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||||
chip.setOnClickListener {
|
chip.setOnClickListener {
|
||||||
queriesChipGroup!!.removeView(chip)
|
queriesChipGroup!!.removeView(chip)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,17 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
|
|
@ -21,6 +24,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.deniscerri.ytdlnis.util.UiUtil
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
|
@ -36,7 +41,10 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
private lateinit var commandTemplateDao: CommandTemplateDao
|
private lateinit var commandTemplateDao: CommandTemplateDao
|
||||||
|
private lateinit var behavior: BottomSheetBehavior<View>
|
||||||
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
|
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
|
||||||
|
private lateinit var uiUtil: UiUtil
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -44,7 +52,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||||
onDownloadItemUpdateListener = listener
|
onDownloadItemUpdateListener = listener
|
||||||
|
uiUtil = UiUtil(FileUtil())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|
@ -58,20 +66,31 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
super.setupDialog(dialog, style)
|
super.setupDialog(dialog, style)
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.configure_download_bottom_sheet, null)
|
val view = LayoutInflater.from(context).inflate(R.layout.configure_download_bottom_sheet, null)
|
||||||
dialog.setContentView(view)
|
dialog.setContentView(view)
|
||||||
//view.minimumHeight = resources.displayMetrics.heightPixels
|
|
||||||
|
dialog.setOnShowListener {
|
||||||
|
behavior = BottomSheetBehavior.from(view.parent as View)
|
||||||
|
val displayMetrics = DisplayMetrics()
|
||||||
|
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||||
|
behavior.peekHeight = displayMetrics.heightPixels - 700
|
||||||
|
}
|
||||||
|
|
||||||
tabLayout = view.findViewById(R.id.download_tablayout)
|
tabLayout = view.findViewById(R.id.download_tablayout)
|
||||||
viewPager2 = view.findViewById(R.id.download_viewpager)
|
viewPager2 = view.findViewById(R.id.download_viewpager)
|
||||||
|
|
||||||
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, downloadItem), DownloadVideoFragment(resultItem, downloadItem))
|
(viewPager2.getChildAt(0) as? RecyclerView)?.apply {
|
||||||
|
isNestedScrollingEnabled = false
|
||||||
|
overScrollMode = View.OVER_SCROLL_NEVER
|
||||||
|
}
|
||||||
|
|
||||||
|
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, downloadItem), DownloadVideoFragment(resultItem, downloadItem))
|
||||||
|
var commandTemplateNr = 0
|
||||||
lifecycleScope.launch{
|
lifecycleScope.launch{
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
val nr = commandTemplateDao.getTotalNumber()
|
commandTemplateNr = commandTemplateDao.getTotalNumber()
|
||||||
if(nr > 0){
|
if(commandTemplateNr > 0){
|
||||||
fragments.add(DownloadCommandFragment(resultItem, downloadItem))
|
fragments.add(DownloadCommandFragment(resultItem, downloadItem))
|
||||||
}else{
|
}else{
|
||||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isEnabled = false
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
|
||||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 0.3f
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 0.3f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +126,12 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
|
|
||||||
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||||
viewPager2.currentItem = tab!!.position
|
if (tab!!.position == 2 && commandTemplateNr == 0){
|
||||||
|
tabLayout.selectTab(tabLayout.getTabAt(1))
|
||||||
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
|
}else{
|
||||||
|
viewPager2.setCurrentItem(tab.position, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||||
|
|
@ -147,6 +171,16 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val link = view.findViewById<Button>(R.id.bottom_sheet_link)
|
||||||
|
link.text = resultItem.url
|
||||||
|
link.setOnClickListener{
|
||||||
|
uiUtil.openLinkIntent(requireContext(), resultItem.url, null)
|
||||||
|
}
|
||||||
|
link.setOnLongClickListener{
|
||||||
|
uiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.graphics.Color
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
|
@ -13,8 +15,10 @@ import android.view.View
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
|
import androidx.core.view.forEach
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
|
|
@ -31,15 +35,19 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
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.chip.ChipGroup
|
import com.google.android.material.chip.ChipGroup
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.slider.RangeSlider
|
import com.google.android.material.slider.RangeSlider
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.lang.reflect.Type
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
|
@ -58,12 +66,17 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
private lateinit var toTextInput : TextInputLayout
|
private lateinit var toTextInput : TextInputLayout
|
||||||
private lateinit var cancelBtn : Button
|
private lateinit var cancelBtn : Button
|
||||||
private lateinit var okBtn : Button
|
private lateinit var okBtn : Button
|
||||||
|
private lateinit var suggestedChips: ChipGroup
|
||||||
|
private lateinit var suggestedChapters : LinearLayout
|
||||||
|
|
||||||
private lateinit var cutListSection : LinearLayout
|
private lateinit var cutListSection : LinearLayout
|
||||||
private lateinit var newCutBtn : Button
|
private lateinit var newCutBtn : Button
|
||||||
|
private lateinit var resetBtn : Button
|
||||||
private lateinit var chipGroup : ChipGroup
|
private lateinit var chipGroup : ChipGroup
|
||||||
|
|
||||||
private var timeSeconds by Delegates.notNull<Int>()
|
private var timeSeconds by Delegates.notNull<Int>()
|
||||||
|
private lateinit var chapters: List<ChapterItem>
|
||||||
|
private lateinit var selectedCuts: MutableList<String>
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -92,6 +105,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
val videoView = view.findViewById<PlayerView>(R.id.video_view)
|
val videoView = view.findViewById<PlayerView>(R.id.video_view)
|
||||||
videoView.player = player
|
videoView.player = player
|
||||||
timeSeconds = convertStringToTimestamp(item.duration)
|
timeSeconds = convertStringToTimestamp(item.duration)
|
||||||
|
chapters = emptyList()
|
||||||
|
|
||||||
//cut section
|
//cut section
|
||||||
cutSection = view.findViewById(R.id.cut_section)
|
cutSection = view.findViewById(R.id.cut_section)
|
||||||
|
|
@ -101,12 +115,25 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
toTextInput = view.findViewById(R.id.to_textinput)
|
toTextInput = view.findViewById(R.id.to_textinput)
|
||||||
cancelBtn = view.findViewById(R.id.cancelButton)
|
cancelBtn = view.findViewById(R.id.cancelButton)
|
||||||
okBtn = view.findViewById(R.id.okButton)
|
okBtn = view.findViewById(R.id.okButton)
|
||||||
|
suggestedChips = view.findViewById(R.id.chapters)
|
||||||
|
suggestedChapters = view.findViewById(R.id.suggested_cuts)
|
||||||
initCutSection()
|
initCutSection()
|
||||||
|
|
||||||
//cut list section
|
//cut list section
|
||||||
cutListSection = view.findViewById(R.id.list_section)
|
cutListSection = view.findViewById(R.id.list_section)
|
||||||
newCutBtn = view.findViewById(R.id.new_cut)
|
newCutBtn = view.findViewById(R.id.new_cut)
|
||||||
|
resetBtn = view.findViewById(R.id.reset_all)
|
||||||
chipGroup = view.findViewById(R.id.cut_list_chip_group)
|
chipGroup = view.findViewById(R.id.cut_list_chip_group)
|
||||||
|
|
||||||
|
selectedCuts = if (chipGroup.childCount == 0){
|
||||||
|
mutableListOf()
|
||||||
|
}else {
|
||||||
|
chipGroup.children.forEach { c ->
|
||||||
|
if ( ! (c as Chip).text.contains(":")) c.isEnabled = false
|
||||||
|
}
|
||||||
|
chipGroup.children.map { (it as Chip).text.toString() }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
initCutListSection()
|
initCutListSection()
|
||||||
|
|
||||||
if (item.downloadSections.isBlank()) cutSection.visibility = View.VISIBLE
|
if (item.downloadSections.isBlank()) cutSection.visibility = View.VISIBLE
|
||||||
|
|
@ -114,26 +141,32 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
val url = withContext(Dispatchers.IO){
|
val data = withContext(Dispatchers.IO){
|
||||||
infoUtil.getStreamingUrl(item.url)
|
infoUtil.getStreamingUrlAndChapters(item.url)
|
||||||
}
|
}
|
||||||
|
if (data.isEmpty()) throw Exception("No Data found!")
|
||||||
|
try{
|
||||||
|
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
||||||
|
chapters = Gson().fromJson(data.first().toString(), listType)
|
||||||
|
}catch (ignored: Exception) {}
|
||||||
|
data.removeFirst()
|
||||||
|
|
||||||
if (url.isBlank()) throw Exception("No Streaming URL found!")
|
|
||||||
|
|
||||||
val urls = url.split("\n")
|
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
||||||
if (urls.size == 2){
|
if (data.size == 2){
|
||||||
val audioSource: MediaSource =
|
val audioSource: MediaSource =
|
||||||
DefaultMediaSourceFactory(requireContext())
|
DefaultMediaSourceFactory(requireContext())
|
||||||
.createMediaSource(fromUri(Uri.parse(urls[0])))
|
.createMediaSource(fromUri(Uri.parse(data[0])))
|
||||||
val videoSource: MediaSource =
|
val videoSource: MediaSource =
|
||||||
DefaultMediaSourceFactory(requireContext())
|
DefaultMediaSourceFactory(requireContext())
|
||||||
.createMediaSource(fromUri(Uri.parse(urls[1])))
|
.createMediaSource(fromUri(Uri.parse(data[1])))
|
||||||
(player as ExoPlayer).setMediaSource(MergingMediaSource(videoSource, audioSource))
|
(player as ExoPlayer).setMediaSource(MergingMediaSource(videoSource, audioSource))
|
||||||
}else{
|
}else{
|
||||||
player.addMediaItem(fromUri(Uri.parse(urls[0])))
|
player.addMediaItem(fromUri(Uri.parse(data[0])))
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.visibility = View.GONE
|
progress.visibility = View.GONE
|
||||||
|
populateSuggestedChapters()
|
||||||
|
|
||||||
player.prepare()
|
player.prepare()
|
||||||
player.seekTo((((rangeSlider.valueFrom.toInt() * timeSeconds) / 100) * 1000).toLong())
|
player.seekTo((((rangeSlider.valueFrom.toInt() * timeSeconds) / 100) * 1000).toLong())
|
||||||
|
|
@ -166,23 +199,8 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initCutSection(){
|
private fun initCutSection(){
|
||||||
if (item.downloadSections.isEmpty()){
|
fromTextInput.editText!!.setText("0:00")
|
||||||
fromTextInput.editText!!.setText("0:00")
|
toTextInput.editText!!.setText(item.duration)
|
||||||
toTextInput.editText!!.setText(item.duration)
|
|
||||||
}else{
|
|
||||||
val stamps = item.downloadSections.split("-")
|
|
||||||
fromTextInput.editText!!.setText(stamps[0])
|
|
||||||
toTextInput.editText!!.setText(stamps[1].replace(";", ""))
|
|
||||||
|
|
||||||
val startSeconds = convertStringToTimestamp(stamps[0])
|
|
||||||
val endSeconds = convertStringToTimestamp(stamps[1].replace(";", ""))
|
|
||||||
|
|
||||||
val startValue = (startSeconds.toFloat() / timeSeconds) * 100
|
|
||||||
val endValue = (endSeconds.toFloat() / timeSeconds) * 100
|
|
||||||
|
|
||||||
rangeSlider.setValues(startValue, endValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rangeSlider.addOnChangeListener { rangeSlider, value, fromUser ->
|
rangeSlider.addOnChangeListener { rangeSlider, value, fromUser ->
|
||||||
val values = rangeSlider.values
|
val values = rangeSlider.values
|
||||||
|
|
@ -270,21 +288,53 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
})
|
})
|
||||||
|
|
||||||
cancelBtn.setOnClickListener {
|
cancelBtn.setOnClickListener {
|
||||||
cutSection.visibility = View.GONE
|
if (chipGroup.childCount == 0){
|
||||||
cutListSection.visibility = View.VISIBLE
|
player.stop()
|
||||||
|
dismiss()
|
||||||
|
}else{
|
||||||
|
cutSection.visibility = View.GONE
|
||||||
|
cutListSection.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
okBtn.isEnabled = false
|
okBtn.isEnabled = false
|
||||||
okBtn.setOnClickListener {
|
okBtn.setOnClickListener {
|
||||||
val chip = createChip("${fromTextInput.editText!!.text}-${toTextInput.editText!!.text}")
|
val chip = createChip("${fromTextInput.editText!!.text}-${toTextInput.editText!!.text}")
|
||||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
|
||||||
chip.performClick()
|
chip.performClick()
|
||||||
player.seekTo((((rangeSlider.valueFrom.toInt() * timeSeconds) / 100) * 1000).toLong())
|
|
||||||
player.play()
|
|
||||||
|
|
||||||
cutSection.visibility = View.GONE
|
cutSection.visibility = View.GONE
|
||||||
cutListSection.visibility = View.VISIBLE
|
cutListSection.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
populateSuggestedChapters()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateSuggestedChapters(){
|
||||||
|
if (chapters.isEmpty()) suggestedChapters.visibility = View.GONE
|
||||||
|
else {
|
||||||
|
suggestedChapters.visibility = View.VISIBLE
|
||||||
|
suggestedChips.removeAllViews()
|
||||||
|
chapters.forEach {
|
||||||
|
val chip = layoutInflater.inflate(R.layout.suggestion_chip, chipGroup, false) as Chip
|
||||||
|
chip.text = it.title
|
||||||
|
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||||
|
chip.isCheckedIconVisible = false
|
||||||
|
suggestedChips.addView(chip)
|
||||||
|
chip.setOnClickListener { c ->
|
||||||
|
val createdChip = createChapterChip(it, null)
|
||||||
|
createdChip.performClick()
|
||||||
|
cutSection.visibility = View.GONE
|
||||||
|
cutListSection.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
//replace existing chip to enable click events
|
||||||
|
if (selectedCuts.contains(it.title)){
|
||||||
|
val idx = selectedCuts.indexOf(it.title)
|
||||||
|
val chipForDeletion = chipGroup.children.firstOrNull { cc -> (cc as Chip).text == it.title }
|
||||||
|
chipGroup.removeView(chipForDeletion)
|
||||||
|
createChapterChip(it, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initCutListSection() {
|
private fun initCutListSection() {
|
||||||
|
|
@ -295,32 +345,44 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
player.seekTo(0)
|
player.seekTo(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetBtn.setOnClickListener {
|
||||||
|
chipGroup.removeAllViews()
|
||||||
|
listener.onChangeCut(emptyList())
|
||||||
|
player.stop()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
if (item.downloadSections.isNotBlank()){
|
if (item.downloadSections.isNotBlank()){
|
||||||
chipGroup.removeAllViews()
|
chipGroup.removeAllViews()
|
||||||
item.downloadSections.split(";").forEachIndexed { index, it ->
|
item.downloadSections.split(";").forEachIndexed { index, it ->
|
||||||
if (it.isBlank()) return
|
if (it.isBlank()) return
|
||||||
val startingValue = ((convertStringToTimestamp(it.split("-")[0]).toFloat() / timeSeconds) * 100).toInt()
|
if (it.contains(":")) createChip(it.replace(";", ""))
|
||||||
val endingValue = ((convertStringToTimestamp(it.split("-")[1].replace(";", "")).toFloat() / timeSeconds) * 100).toInt()
|
else createChapterChip(ChapterItem(0, 0, it), null)
|
||||||
|
|
||||||
createChip(it.replace(";", ""))
|
|
||||||
if (index == 0) rangeSlider.setValues(startingValue.toFloat(), endingValue.toFloat())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createChip(timestamp: String) : Chip {
|
private fun createChip(timestamp: String) : Chip {
|
||||||
val startingValue = ((convertStringToTimestamp(timestamp.split("-")[0]).toFloat() / timeSeconds) * 100).toInt()
|
val startTimestamp = convertStringToTimestamp(timestamp.split("-")[0].replace(";", ""))
|
||||||
val endingValue = ((convertStringToTimestamp(timestamp.split("-")[1].replace(";", "")).toFloat() / timeSeconds) * 100).toInt()
|
val endTimestamp = convertStringToTimestamp(timestamp.split("-")[1].replace(";", ""))
|
||||||
|
|
||||||
|
val startingValue = ((startTimestamp.toFloat() / timeSeconds) * 100).toInt()
|
||||||
|
val endingValue = ((endTimestamp.toFloat() / timeSeconds) * 100).toInt()
|
||||||
|
|
||||||
val chip = layoutInflater.inflate(R.layout.filter_chip, chipGroup, false) as Chip
|
val chip = layoutInflater.inflate(R.layout.filter_chip, chipGroup, false) as Chip
|
||||||
chip.text = timestamp
|
chip.text = timestamp
|
||||||
|
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||||
chip.isCheckedIconVisible = false
|
chip.isCheckedIconVisible = false
|
||||||
chipGroup.addView(chip)
|
chipGroup.addView(chip)
|
||||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
selectedCuts.add(chip.text.toString())
|
||||||
|
listener.onChangeCut(selectedCuts)
|
||||||
|
|
||||||
chip.setOnClickListener {
|
chip.setOnClickListener {
|
||||||
if (chip.isChecked) {
|
if (chip.isChecked) {
|
||||||
rangeSlider.setValues(startingValue.toFloat(), endingValue.toFloat())
|
rangeSlider.setValues(startingValue.toFloat(), endingValue.toFloat())
|
||||||
|
player.prepare()
|
||||||
|
player.seekTo((((startingValue * timeSeconds) / 100) * 1000).toLong())
|
||||||
|
player.play()
|
||||||
}else {
|
}else {
|
||||||
player.seekTo(0)
|
player.seekTo(0)
|
||||||
player.pause()
|
player.pause()
|
||||||
|
|
@ -335,7 +397,8 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
player.seekTo(0)
|
player.seekTo(0)
|
||||||
player.pause()
|
player.pause()
|
||||||
chipGroup.removeView(chip)
|
chipGroup.removeView(chip)
|
||||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
selectedCuts.remove(chip.text.toString())
|
||||||
|
listener.onChangeCut(selectedCuts)
|
||||||
}
|
}
|
||||||
deleteDialog.show()
|
deleteDialog.show()
|
||||||
true
|
true
|
||||||
|
|
@ -344,6 +407,60 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
return chip
|
return chip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createChapterChip(chapter: ChapterItem, position: Int?) : Chip {
|
||||||
|
val chip = layoutInflater.inflate(R.layout.filter_chip, chipGroup, false) as Chip
|
||||||
|
chip.text = chapter.title
|
||||||
|
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||||
|
chip.isCheckedIconVisible = false
|
||||||
|
|
||||||
|
if (position != null) chipGroup.addView(chip, position)
|
||||||
|
else chipGroup.addView(chip)
|
||||||
|
|
||||||
|
if (! selectedCuts.contains(chapter.title))
|
||||||
|
selectedCuts.add(chip.text.toString())
|
||||||
|
|
||||||
|
listener.onChangeCut(selectedCuts)
|
||||||
|
if (chapter.start_time == 0L && chapter.end_time == 0L) {
|
||||||
|
chip.isEnabled = false
|
||||||
|
}else{
|
||||||
|
val startTimestamp = chapter.start_time.toInt()
|
||||||
|
val endTimestamp = chapter.end_time.toInt()
|
||||||
|
|
||||||
|
val startingValue = ((startTimestamp.toFloat() / timeSeconds) * 100).toInt()
|
||||||
|
val endingValue = ((endTimestamp.toFloat() / timeSeconds) * 100).toInt()
|
||||||
|
|
||||||
|
chip.setOnClickListener {
|
||||||
|
if (chip.isChecked) {
|
||||||
|
rangeSlider.setValues(startingValue.toFloat(), endingValue.toFloat())
|
||||||
|
player.prepare()
|
||||||
|
player.seekTo((((startingValue * timeSeconds) / 100) * 1000).toLong())
|
||||||
|
player.play()
|
||||||
|
}else {
|
||||||
|
player.seekTo(0)
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chip.setOnLongClickListener {
|
||||||
|
val deleteDialog = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + chip.text + "\"!")
|
||||||
|
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
|
||||||
|
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
|
||||||
|
player.seekTo(0)
|
||||||
|
player.pause()
|
||||||
|
chipGroup.removeView(chip)
|
||||||
|
selectedCuts.remove(chip.text.toString())
|
||||||
|
listener.onChangeCut(selectedCuts)
|
||||||
|
}
|
||||||
|
deleteDialog.show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chip
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun videoProgress(player: Player?) = flow {
|
private fun videoProgress(player: Player?) = flow {
|
||||||
while (true) {
|
while (true) {
|
||||||
emit((player!!.currentPosition / 1000).toInt())
|
emit((player!!.currentPosition / 1000).toInt())
|
||||||
|
|
@ -386,5 +503,5 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VideoCutListener{
|
interface VideoCutListener{
|
||||||
fun onChangeCut(list: Sequence<String>)
|
fun onChangeCut(list: List<String>)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package com.deniscerri.ytdlnis.ui.downloadcard
|
package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ClipboardManager
|
import android.content.*
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
|
@ -11,10 +9,7 @@ import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.*
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.AutoCompleteTextView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|
@ -249,10 +244,10 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
val cut = view.findViewById<Chip>(R.id.cut)
|
val cut = view.findViewById<Chip>(R.id.cut)
|
||||||
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
||||||
val cutVideoListener = object : VideoCutListener {
|
val cutVideoListener = object : VideoCutListener {
|
||||||
override fun onChangeCut(list: Sequence<String>) {
|
override fun onChangeCut(list: List<String>) {
|
||||||
if (list.count() == 0){
|
if (list.isEmpty()){
|
||||||
downloadItem.downloadSections = ""
|
downloadItem.downloadSections = ""
|
||||||
cut.text = ""
|
cut.text = getString(R.string.cut)
|
||||||
|
|
||||||
splitByChapters.isEnabled = true
|
splitByChapters.isEnabled = true
|
||||||
splitByChapters.isChecked = downloadItem.audioPreferences.splitByChapters
|
splitByChapters.isChecked = downloadItem.audioPreferences.splitByChapters
|
||||||
|
|
@ -274,13 +269,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
||||||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||||
}
|
}
|
||||||
|
|
||||||
val copyURL = view.findViewById<Chip>(R.id.copy_url)
|
|
||||||
copyURL.setOnClickListener {
|
|
||||||
val clipboard: ClipboardManager =
|
|
||||||
requireContext().getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
clipboard.setText(downloadItem.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
}catch (e : Exception){
|
}catch (e : Exception){
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,14 +83,14 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, null), DownloadVideoFragment(resultItem, null))
|
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, null), DownloadVideoFragment(resultItem, null))
|
||||||
|
var commandTemplateNr = 0
|
||||||
lifecycleScope.launch{
|
lifecycleScope.launch{
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
val nr = commandTemplateDao.getTotalNumber()
|
commandTemplateNr = commandTemplateDao.getTotalNumber()
|
||||||
if(nr > 0){
|
if(commandTemplateNr > 0){
|
||||||
fragments.add(DownloadCommandFragment(resultItem, null))
|
fragments.add(DownloadCommandFragment(resultItem, null))
|
||||||
}else{
|
}else{
|
||||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isEnabled = false
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
|
||||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 0.3f
|
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 0.3f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -128,7 +128,12 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
|
|
||||||
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||||
viewPager2.setCurrentItem(tab!!.position, false)
|
if (tab!!.position == 2 && commandTemplateNr == 0){
|
||||||
|
tabLayout.selectTab(tabLayout.getTabAt(1))
|
||||||
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
|
}else{
|
||||||
|
viewPager2.setCurrentItem(tab.position, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
override fun onTabUnselected(tab: TabLayout.Tab?) {
|
||||||
|
|
@ -168,6 +173,16 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
||||||
}
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val link = view.findViewById<Button>(R.id.bottom_sheet_link)
|
||||||
|
link.text = resultItem.url
|
||||||
|
link.setOnClickListener{
|
||||||
|
uiUtil.openLinkIntent(requireContext(), resultItem.url, null)
|
||||||
|
}
|
||||||
|
link.setOnLongClickListener{
|
||||||
|
uiUtil.copyLinkToClipBoard(requireContext(), resultItem.url, null)
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDownloadItem() : DownloadItem{
|
private fun getDownloadItem() : DownloadItem{
|
||||||
|
|
|
||||||
|
|
@ -192,13 +192,6 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val copyURL = view.findViewById<Chip>(R.id.copy_url)
|
|
||||||
copyURL.setOnClickListener {
|
|
||||||
val clipboard: ClipboardManager =
|
|
||||||
requireContext().getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
clipboard.setText(downloadItem.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@ import android.text.TextWatcher
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.*
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.AutoCompleteTextView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
|
@ -269,8 +266,8 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
||||||
val cutVideoListener = object : VideoCutListener {
|
val cutVideoListener = object : VideoCutListener {
|
||||||
|
|
||||||
override fun onChangeCut(list: Sequence<String>) {
|
override fun onChangeCut(list: List<String>) {
|
||||||
if (list.count() == 0){
|
if (list.isEmpty()){
|
||||||
downloadItem.downloadSections = ""
|
downloadItem.downloadSections = ""
|
||||||
cut.text = getString(R.string.cut)
|
cut.text = getString(R.string.cut)
|
||||||
|
|
||||||
|
|
@ -302,13 +299,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
||||||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||||
}
|
}
|
||||||
|
|
||||||
val copyURL = view.findViewById<Chip>(R.id.copy_url)
|
|
||||||
copyURL.setOnClickListener {
|
|
||||||
val clipboard: ClipboardManager =
|
|
||||||
requireContext().getSystemService(AppCompatActivity.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
clipboard.setText(downloadItem.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@ package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.*
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
@ -109,13 +108,21 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem, private v
|
||||||
linearLayout.removeAllViews()
|
linearLayout.removeAllViews()
|
||||||
Log.e("aa", formats.toString())
|
Log.e("aa", formats.toString())
|
||||||
for (i in formats.lastIndex downTo 0){
|
for (i in formats.lastIndex downTo 0){
|
||||||
val it = formats[i]
|
val format = formats[i]
|
||||||
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
val formatItem = LayoutInflater.from(context).inflate(R.layout.format_item, null)
|
||||||
uiUtil.populateFormatCard(formatItem as ConstraintLayout, it)
|
uiUtil.populateFormatCard(formatItem as ConstraintLayout, format)
|
||||||
formatItem.setOnClickListener{_ ->
|
formatItem.setOnClickListener{_ ->
|
||||||
listener.onFormatClick(formats, it)
|
listener.onFormatClick(formats, format)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
formatItem.setOnLongClickListener {
|
||||||
|
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
|
val clip = ClipData.newPlainText("format_id", format.format_id)
|
||||||
|
clipboard.setPrimaryClip(clip)
|
||||||
|
Toast.makeText(context, requireContext().getString(R.string.formatid_copied_to_clipboard), Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
true
|
||||||
|
}
|
||||||
linearLayout.addView(formatItem)
|
linearLayout.addView(formatItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -629,10 +629,11 @@ class InfoUtil(context: Context) {
|
||||||
return format
|
return format
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStreamingUrl(url: String) : String {
|
fun getStreamingUrlAndChapters(url: String) : MutableList<String?> {
|
||||||
try {
|
try {
|
||||||
val request = YoutubeDLRequest(url)
|
val request = YoutubeDLRequest(url)
|
||||||
request.addOption("-j")
|
request.addOption("--get-url")
|
||||||
|
request.addOption("--print", "%(chapters)s")
|
||||||
request.addOption("--skip-download")
|
request.addOption("--skip-download")
|
||||||
request.addOption("-R", "1")
|
request.addOption("-R", "1")
|
||||||
request.addOption("--socket-timeout", "5")
|
request.addOption("--socket-timeout", "5")
|
||||||
|
|
@ -643,10 +644,9 @@ class InfoUtil(context: Context) {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
arrayOf(youtubeDLResponse.out)
|
arrayOf(youtubeDLResponse.out)
|
||||||
}
|
}
|
||||||
val jsonObject = JSONObject(results[0]!!)
|
return results.toMutableList()
|
||||||
return jsonObject.getString("urls")
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return ""
|
return mutableListOf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,9 +118,13 @@ class DownloadWorker(
|
||||||
if (downloadItem.downloadSections.isNotBlank()){
|
if (downloadItem.downloadSections.isNotBlank()){
|
||||||
downloadItem.downloadSections.split(";").forEach {
|
downloadItem.downloadSections.split(";").forEach {
|
||||||
if (it.isBlank()) return@forEach
|
if (it.isBlank()) return@forEach
|
||||||
request.addOption("--download-sections", "*$it")
|
if (it.contains(":"))
|
||||||
|
request.addOption("--download-sections", "*$it")
|
||||||
|
else
|
||||||
|
request.addOption("--download-sections", it)
|
||||||
}
|
}
|
||||||
downloadItem.customFileNameTemplate += "%(autonumber)s"
|
downloadItem.customFileNameTemplate += " %(section_title)s %(autonumber)s"
|
||||||
|
request.addOption("--output-na-placeholder", " ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,9 +134,8 @@ class DownloadWorker(
|
||||||
|
|
||||||
when(type){
|
when(type){
|
||||||
DownloadViewModel.Type.audio -> {
|
DownloadViewModel.Type.audio -> {
|
||||||
request.addOption("-x")
|
|
||||||
var audioQualityId : String = downloadItem.format.format_id
|
var audioQualityId : String = downloadItem.format.format_id
|
||||||
if (audioQualityId.isBlank() || audioQualityId == "0" || audioQualityId == context.getString(R.string.best_quality)) audioQualityId = ""
|
if (audioQualityId.isBlank() || audioQualityId == "0" || audioQualityId == context.getString(R.string.best_quality)) audioQualityId = "bestaudio"
|
||||||
else if (audioQualityId == context.getString(R.string.worst_quality)) audioQualityId = "worstaudio"
|
else if (audioQualityId == context.getString(R.string.worst_quality)) audioQualityId = "worstaudio"
|
||||||
|
|
||||||
if (audioQualityId.isNotBlank()){
|
if (audioQualityId.isNotBlank()){
|
||||||
|
|
@ -141,18 +144,33 @@ class DownloadWorker(
|
||||||
|
|
||||||
val ext = downloadItem.format.container
|
val ext = downloadItem.format.container
|
||||||
if(ext != context.getString(R.string.defaultValue) && ext != "webm"){
|
if(ext != context.getString(R.string.defaultValue) && ext != "webm"){
|
||||||
request.addOption("--audio-format", ext)
|
val codec = when(downloadItem.format.container){
|
||||||
|
"m4a" -> "aac"
|
||||||
|
"aac" -> "aac"
|
||||||
|
"mp3" -> "libmp3lame"
|
||||||
|
"flac" -> "flac"
|
||||||
|
"opus" -> "libopus"
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
Log.e("aa", codec)
|
||||||
|
if (codec.isEmpty()){
|
||||||
|
request.addOption("-x")
|
||||||
|
}else{
|
||||||
|
request.addOption("--remux-video", ext)
|
||||||
|
request.addOption("--ppa", "VideoRemuxer:-c:a $codec")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.addOption("--embed-metadata")
|
request.addOption("--embed-metadata")
|
||||||
|
|
||||||
if (downloadItem.audioPreferences.embedThumb) {
|
if (downloadItem.audioPreferences.embedThumb) {
|
||||||
request.addOption("--embed-thumbnail")
|
request.addOption("--embed-thumbnail")
|
||||||
request.addOption("--convert-thumbnails", "png")
|
request.addOption("--convert-thumbnails", "jpg")
|
||||||
try {
|
try {
|
||||||
val config = File(context.cacheDir.absolutePath + "/downloads/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
|
val config = File(context.cacheDir.absolutePath + "/downloads/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
|
||||||
val configData =
|
val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||||
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
|
||||||
config.writeText(configData)
|
config.writeText(configData)
|
||||||
|
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
||||||
request.addOption("--config", config.absolutePath)
|
request.addOption("--config", config.absolutePath)
|
||||||
} catch (ignored: Exception) {}
|
} catch (ignored: Exception) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
app:strokeWidth="0dp"
|
app:strokeWidth="0dp"
|
||||||
app:cardPreventCornerOverlap="true"
|
app:cardPreventCornerOverlap="true"
|
||||||
android:layout_margin="10dp">
|
android:layout_margin="20dp">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/image_view"
|
android:id="@+id/image_view"
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/download_viewpager"
|
android:id="@+id/download_viewpager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<include layout="@layout/history_no_results"
|
<include layout="@layout/history_no_results"
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,16 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bottom_sheet_link"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton.Icon"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:icon="@drawable/ic_link" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="15dp"
|
android:layout_marginHorizontal="15dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toTopOf="@id/suggested_cuts"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.533"
|
app:layout_constraintHorizontal_bias="0.533"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
@ -119,6 +119,43 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/suggested_cuts"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.533"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/linearLayout5"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/suggested" />
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/chapters"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
app:chipSpacing="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -127,7 +164,7 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_marginHorizontal="20dp"
|
android:layout_marginHorizontal="20dp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/linearLayout5"
|
app:layout_constraintTop_toBottomOf="@+id/suggested_cuts"
|
||||||
app:layout_constraintVertical_bias="1.0"
|
app:layout_constraintVertical_bias="1.0"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|
@ -180,6 +217,17 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/reset_all"
|
||||||
|
style="?attr/materialIconButtonFilledTonalStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:icon="@drawable/ic_baseline_delete_outline_24"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/new_cut"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/new_cut"
|
android:id="@+id/new_cut"
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,18 @@
|
||||||
android:id="@+id/download_viewpager"
|
android:id="@+id/download_viewpager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bottom_sheet_link"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton.Icon"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@string/app_name"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:icon="@drawable/ic_link" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="10dp"
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="10dp"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingVertical="5dp"
|
android:paddingVertical="5dp"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:focusable="true">
|
android:focusable="true">
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:paddingHorizontal="10dp"
|
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="10dp"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
|
@ -20,7 +19,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:paddingBottom="10dp"
|
android:padding="10dp"
|
||||||
android:hint="@string/title"
|
android:hint="@string/title"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
|
@ -35,7 +34,7 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:padding="10dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
|
@ -80,13 +79,16 @@
|
||||||
android:id="@+id/audio_quality_title"
|
android:id="@+id/audio_quality_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
android:text="@string/audio_quality" />
|
android:text="@string/audio_quality" />
|
||||||
<include layout="@layout/format_item" />
|
<include layout="@layout/format_item" />
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/outputPath"
|
android:id="@+id/outputPath"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -102,8 +104,7 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/freespace"
|
android:id="@+id/freespace"
|
||||||
android:paddingHorizontal="10dp"
|
android:paddingHorizontal="20dp"
|
||||||
android:paddingVertical="5dp"
|
|
||||||
android:textSize="13sp"
|
android:textSize="13sp"
|
||||||
android:textColor="@android:color/tab_indicator_text"
|
android:textColor="@android:color/tab_indicator_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
@ -112,7 +113,7 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/adjust_audio"
|
android:id="@+id/adjust_audio"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:paddingVertical="10dp"
|
android:padding="10dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
>
|
>
|
||||||
|
|
@ -205,22 +206,6 @@
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/copy_url"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/copy_url"
|
|
||||||
app:chipIconVisible="true"
|
|
||||||
app:chipIcon="@drawable/ic_clipboard"
|
|
||||||
android:minWidth="30dp"
|
|
||||||
app:cornerRadius="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,21 +111,6 @@
|
||||||
android:text="@string/edit_selected"
|
android:text="@string/edit_selected"
|
||||||
app:chipIcon="@drawable/ic_edit" />
|
app:chipIcon="@drawable/ic_edit" />
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/copy_url"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/copy_url"
|
|
||||||
app:chipIconVisible="true"
|
|
||||||
app:chipIcon="@drawable/ic_clipboard"
|
|
||||||
android:minWidth="30dp"
|
|
||||||
app:cornerRadius="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
|
@ -20,7 +19,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:hint="@string/title"
|
android:hint="@string/title"
|
||||||
android:paddingBottom="10dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -33,7 +32,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingBottom="10dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/author_textinput"
|
android:id="@+id/author_textinput"
|
||||||
|
|
@ -74,6 +73,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="10dp"
|
||||||
android:text="@string/video_quality" />
|
android:text="@string/video_quality" />
|
||||||
|
|
||||||
<include layout="@layout/format_item" />
|
<include layout="@layout/format_item" />
|
||||||
|
|
@ -85,7 +85,9 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/save_dir"
|
android:hint="@string/save_dir"
|
||||||
android:paddingTop="10dp">
|
android:paddingHorizontal="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="0dp">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -97,8 +99,7 @@
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/freespace"
|
android:id="@+id/freespace"
|
||||||
android:paddingHorizontal="10dp"
|
android:paddingHorizontal="20dp"
|
||||||
android:paddingVertical="5dp"
|
|
||||||
android:textSize="13sp"
|
android:textSize="13sp"
|
||||||
android:textColor="@android:color/tab_indicator_text"
|
android:textColor="@android:color/tab_indicator_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
@ -110,7 +111,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingVertical="10dp">
|
android:padding="10dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
@ -213,24 +214,6 @@
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/copy_url"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/copy_url"
|
|
||||||
app:chipIconVisible="true"
|
|
||||||
app:chipIcon="@drawable/ic_clipboard"
|
|
||||||
android:minWidth="30dp"
|
|
||||||
app:cornerRadius="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/queries"
|
android:id="@+id/queries"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,8 @@
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/shortcutsChipGroup"
|
android:id="@+id/shortcutsChipGroup"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
app:chipSpacingVertical="0dp"
|
app:chipSpacingVertical="-10dp"
|
||||||
|
app:chipSpacing="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:singleLine="false">
|
app:singleLine="false">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,4 +192,7 @@
|
||||||
<string name="ignore_battery_optimization">Ignore Battery Optimization</string>
|
<string name="ignore_battery_optimization">Ignore Battery Optimization</string>
|
||||||
<string name="cut">Cut</string>
|
<string name="cut">Cut</string>
|
||||||
<string name="new_cut">New Cut</string>
|
<string name="new_cut">New Cut</string>
|
||||||
|
<string name="add_template_first">You need to have at least one command template created!</string>
|
||||||
|
<string name="formatid_copied_to_clipboard">Format ID copied to clipboard</string>
|
||||||
|
<string name="suggested">Suggested</string>
|
||||||
</resources>
|
</resources>
|
||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
#Sun Mar 05 19:03:41 CET 2023
|
#Sat Apr 08 15:57:50 CEST 2023
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue