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"]
|
||||
}
|
||||
}
|
||||
compileSdkVersion "android-UpsideDownCake"
|
||||
compileSdkVersion 33
|
||||
defaultConfig {
|
||||
applicationId "com.deniscerri.ytdl"
|
||||
minSdkVersion 23
|
||||
|
|
@ -119,7 +119,7 @@ dependencies {
|
|||
|
||||
implementation "androidx.appcompat:appcompat:$appCompatVer"
|
||||
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.core:core:1.9.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.content.*
|
||||
import android.content.Context.CLIPBOARD_SERVICE
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.View.*
|
||||
import android.widget.*
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.text.TextUtilsCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
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.chip.Chip
|
||||
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.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.search.SearchBar
|
||||
|
|
@ -350,6 +355,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
if (present == null) {
|
||||
val chip = layoutinflater!!.inflate(R.layout.input_chip, queriesChipGroup, false) as Chip
|
||||
chip.text = searchView.editText.text
|
||||
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||
chip.setOnClickListener {
|
||||
queriesChipGroup!!.removeView(chip)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,17 @@ import android.annotation.SuppressLint
|
|||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.deniscerri.ytdlnis.R
|
||||
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.Type
|
||||
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.BottomSheetDialogFragment
|
||||
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 resultViewModel: ResultViewModel
|
||||
private lateinit var commandTemplateDao: CommandTemplateDao
|
||||
private lateinit var behavior: BottomSheetBehavior<View>
|
||||
private lateinit var onDownloadItemUpdateListener: OnDownloadItemUpdateListener
|
||||
private lateinit var uiUtil: UiUtil
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -44,7 +52,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
|||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||
onDownloadItemUpdateListener = listener
|
||||
|
||||
uiUtil = UiUtil(FileUtil())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
|
@ -58,20 +66,31 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
|||
super.setupDialog(dialog, style)
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.configure_download_bottom_sheet, null)
|
||||
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)
|
||||
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{
|
||||
withContext(Dispatchers.IO){
|
||||
val nr = commandTemplateDao.getTotalNumber()
|
||||
if(nr > 0){
|
||||
commandTemplateNr = commandTemplateDao.getTotalNumber()
|
||||
if(commandTemplateNr > 0){
|
||||
fragments.add(DownloadCommandFragment(resultItem, downloadItem))
|
||||
}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
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +126,12 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
|||
|
||||
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
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?) {
|
||||
|
|
@ -147,6 +171,16 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri
|
|||
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.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
|
|
@ -13,8 +15,10 @@ import android.view.View
|
|||
import android.widget.*
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.forEach
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
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.chip.Chip
|
||||
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.slider.RangeSlider
|
||||
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.delay
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.lang.reflect.Type
|
||||
import java.util.*
|
||||
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 cancelBtn : Button
|
||||
private lateinit var okBtn : Button
|
||||
private lateinit var suggestedChips: ChipGroup
|
||||
private lateinit var suggestedChapters : LinearLayout
|
||||
|
||||
private lateinit var cutListSection : LinearLayout
|
||||
private lateinit var newCutBtn : Button
|
||||
private lateinit var resetBtn : Button
|
||||
private lateinit var chipGroup : ChipGroup
|
||||
|
||||
private var timeSeconds by Delegates.notNull<Int>()
|
||||
private lateinit var chapters: List<ChapterItem>
|
||||
private lateinit var selectedCuts: MutableList<String>
|
||||
|
||||
|
||||
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)
|
||||
videoView.player = player
|
||||
timeSeconds = convertStringToTimestamp(item.duration)
|
||||
chapters = emptyList()
|
||||
|
||||
//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)
|
||||
cancelBtn = view.findViewById(R.id.cancelButton)
|
||||
okBtn = view.findViewById(R.id.okButton)
|
||||
suggestedChips = view.findViewById(R.id.chapters)
|
||||
suggestedChapters = view.findViewById(R.id.suggested_cuts)
|
||||
initCutSection()
|
||||
|
||||
//cut list section
|
||||
cutListSection = view.findViewById(R.id.list_section)
|
||||
newCutBtn = view.findViewById(R.id.new_cut)
|
||||
resetBtn = view.findViewById(R.id.reset_all)
|
||||
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()
|
||||
|
||||
if (item.downloadSections.isBlank()) cutSection.visibility = View.VISIBLE
|
||||
|
|
@ -114,26 +141,32 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val url = withContext(Dispatchers.IO){
|
||||
infoUtil.getStreamingUrl(item.url)
|
||||
val data = withContext(Dispatchers.IO){
|
||||
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 (urls.size == 2){
|
||||
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
||||
if (data.size == 2){
|
||||
val audioSource: MediaSource =
|
||||
DefaultMediaSourceFactory(requireContext())
|
||||
.createMediaSource(fromUri(Uri.parse(urls[0])))
|
||||
.createMediaSource(fromUri(Uri.parse(data[0])))
|
||||
val videoSource: MediaSource =
|
||||
DefaultMediaSourceFactory(requireContext())
|
||||
.createMediaSource(fromUri(Uri.parse(urls[1])))
|
||||
.createMediaSource(fromUri(Uri.parse(data[1])))
|
||||
(player as ExoPlayer).setMediaSource(MergingMediaSource(videoSource, audioSource))
|
||||
}else{
|
||||
player.addMediaItem(fromUri(Uri.parse(urls[0])))
|
||||
player.addMediaItem(fromUri(Uri.parse(data[0])))
|
||||
}
|
||||
|
||||
progress.visibility = View.GONE
|
||||
populateSuggestedChapters()
|
||||
|
||||
player.prepare()
|
||||
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(){
|
||||
if (item.downloadSections.isEmpty()){
|
||||
fromTextInput.editText!!.setText("0:00")
|
||||
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)
|
||||
}
|
||||
|
||||
fromTextInput.editText!!.setText("0:00")
|
||||
toTextInput.editText!!.setText(item.duration)
|
||||
|
||||
rangeSlider.addOnChangeListener { rangeSlider, value, fromUser ->
|
||||
val values = rangeSlider.values
|
||||
|
|
@ -270,21 +288,53 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
})
|
||||
|
||||
cancelBtn.setOnClickListener {
|
||||
cutSection.visibility = View.GONE
|
||||
cutListSection.visibility = View.VISIBLE
|
||||
if (chipGroup.childCount == 0){
|
||||
player.stop()
|
||||
dismiss()
|
||||
}else{
|
||||
cutSection.visibility = View.GONE
|
||||
cutListSection.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
okBtn.isEnabled = false
|
||||
okBtn.setOnClickListener {
|
||||
val chip = createChip("${fromTextInput.editText!!.text}-${toTextInput.editText!!.text}")
|
||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
||||
chip.performClick()
|
||||
player.seekTo((((rangeSlider.valueFrom.toInt() * timeSeconds) / 100) * 1000).toLong())
|
||||
player.play()
|
||||
|
||||
cutSection.visibility = View.GONE
|
||||
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() {
|
||||
|
|
@ -295,32 +345,44 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
player.seekTo(0)
|
||||
}
|
||||
|
||||
resetBtn.setOnClickListener {
|
||||
chipGroup.removeAllViews()
|
||||
listener.onChangeCut(emptyList())
|
||||
player.stop()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
if (item.downloadSections.isNotBlank()){
|
||||
chipGroup.removeAllViews()
|
||||
item.downloadSections.split(";").forEachIndexed { index, it ->
|
||||
if (it.isBlank()) return
|
||||
val startingValue = ((convertStringToTimestamp(it.split("-")[0]).toFloat() / timeSeconds) * 100).toInt()
|
||||
val endingValue = ((convertStringToTimestamp(it.split("-")[1].replace(";", "")).toFloat() / timeSeconds) * 100).toInt()
|
||||
|
||||
createChip(it.replace(";", ""))
|
||||
if (index == 0) rangeSlider.setValues(startingValue.toFloat(), endingValue.toFloat())
|
||||
if (it.contains(":")) createChip(it.replace(";", ""))
|
||||
else createChapterChip(ChapterItem(0, 0, it), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createChip(timestamp: String) : Chip {
|
||||
val startingValue = ((convertStringToTimestamp(timestamp.split("-")[0]).toFloat() / timeSeconds) * 100).toInt()
|
||||
val endingValue = ((convertStringToTimestamp(timestamp.split("-")[1].replace(";", "")).toFloat() / timeSeconds) * 100).toInt()
|
||||
val startTimestamp = convertStringToTimestamp(timestamp.split("-")[0].replace(";", ""))
|
||||
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
|
||||
chip.text = timestamp
|
||||
chip.chipBackgroundColor = ColorStateList.valueOf(MaterialColors.getColor(requireContext(), R.attr.colorSecondaryContainer, Color.BLACK))
|
||||
chip.isCheckedIconVisible = false
|
||||
chipGroup.addView(chip)
|
||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
||||
selectedCuts.add(chip.text.toString())
|
||||
listener.onChangeCut(selectedCuts)
|
||||
|
||||
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()
|
||||
|
|
@ -335,7 +397,8 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
player.seekTo(0)
|
||||
player.pause()
|
||||
chipGroup.removeView(chip)
|
||||
listener.onChangeCut(chipGroup.children.map { c -> (c as Chip).text.toString() })
|
||||
selectedCuts.remove(chip.text.toString())
|
||||
listener.onChangeCut(selectedCuts)
|
||||
}
|
||||
deleteDialog.show()
|
||||
true
|
||||
|
|
@ -344,6 +407,60 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
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 {
|
||||
while (true) {
|
||||
emit((player!!.currentPosition / 1000).toInt())
|
||||
|
|
@ -386,5 +503,5 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val list
|
|||
}
|
||||
|
||||
interface VideoCutListener{
|
||||
fun onChangeCut(list: Sequence<String>)
|
||||
fun onChangeCut(list: List<String>)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package com.deniscerri.ytdlnis.ui.downloadcard
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ClipboardManager
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.*
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
|
|
@ -11,10 +9,7 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
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)
|
||||
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
||||
val cutVideoListener = object : VideoCutListener {
|
||||
override fun onChangeCut(list: Sequence<String>) {
|
||||
if (list.count() == 0){
|
||||
override fun onChangeCut(list: List<String>) {
|
||||
if (list.isEmpty()){
|
||||
downloadItem.downloadSections = ""
|
||||
cut.text = ""
|
||||
cut.text = getString(R.string.cut)
|
||||
|
||||
splitByChapters.isEnabled = true
|
||||
splitByChapters.isChecked = downloadItem.audioPreferences.splitByChapters
|
||||
|
|
@ -274,13 +269,6 @@ class DownloadAudioFragment(private var resultItem: ResultItem, private var curr
|
|||
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){
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,14 +83,14 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
|||
}
|
||||
|
||||
val fragments = mutableListOf<Fragment>(DownloadAudioFragment(resultItem, null), DownloadVideoFragment(resultItem, null))
|
||||
|
||||
var commandTemplateNr = 0
|
||||
lifecycleScope.launch{
|
||||
withContext(Dispatchers.IO){
|
||||
val nr = commandTemplateDao.getTotalNumber()
|
||||
if(nr > 0){
|
||||
commandTemplateNr = commandTemplateDao.getTotalNumber()
|
||||
if(commandTemplateNr > 0){
|
||||
fragments.add(DownloadCommandFragment(resultItem, null))
|
||||
}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
|
||||
}
|
||||
}
|
||||
|
|
@ -128,7 +128,12 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
|||
|
||||
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||
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?) {
|
||||
|
|
@ -168,6 +173,16 @@ class DownloadBottomSheetDialog(private val resultItem: ResultItem, private val
|
|||
}
|
||||
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{
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ import android.text.TextWatcher
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.TextView
|
||||
import android.widget.*
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
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
|
||||
val cutVideoListener = object : VideoCutListener {
|
||||
|
||||
override fun onChangeCut(list: Sequence<String>) {
|
||||
if (list.count() == 0){
|
||||
override fun onChangeCut(list: List<String>) {
|
||||
if (list.isEmpty()){
|
||||
downloadItem.downloadSections = ""
|
||||
cut.text = getString(R.string.cut)
|
||||
|
||||
|
|
@ -302,13 +299,6 @@ class DownloadVideoFragment(private val resultItem: ResultItem, private var curr
|
|||
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) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ package com.deniscerri.ytdlnis.ui.downloadcard
|
|||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.content.*
|
||||
import android.os.Bundle
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.Log
|
||||
|
|
@ -109,13 +108,21 @@ class FormatSelectionBottomSheetDialog(private val item: DownloadItem, private v
|
|||
linearLayout.removeAllViews()
|
||||
Log.e("aa", formats.toString())
|
||||
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)
|
||||
uiUtil.populateFormatCard(formatItem as ConstraintLayout, it)
|
||||
uiUtil.populateFormatCard(formatItem as ConstraintLayout, format)
|
||||
formatItem.setOnClickListener{_ ->
|
||||
listener.onFormatClick(formats, it)
|
||||
listener.onFormatClick(formats, format)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -629,10 +629,11 @@ class InfoUtil(context: Context) {
|
|||
return format
|
||||
}
|
||||
|
||||
fun getStreamingUrl(url: String) : String {
|
||||
fun getStreamingUrlAndChapters(url: String) : MutableList<String?> {
|
||||
try {
|
||||
val request = YoutubeDLRequest(url)
|
||||
request.addOption("-j")
|
||||
request.addOption("--get-url")
|
||||
request.addOption("--print", "%(chapters)s")
|
||||
request.addOption("--skip-download")
|
||||
request.addOption("-R", "1")
|
||||
request.addOption("--socket-timeout", "5")
|
||||
|
|
@ -643,10 +644,9 @@ class InfoUtil(context: Context) {
|
|||
} catch (e: Exception) {
|
||||
arrayOf(youtubeDLResponse.out)
|
||||
}
|
||||
val jsonObject = JSONObject(results[0]!!)
|
||||
return jsonObject.getString("urls")
|
||||
return results.toMutableList()
|
||||
} catch (e: Exception) {
|
||||
return ""
|
||||
return mutableListOf()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,9 +118,13 @@ class DownloadWorker(
|
|||
if (downloadItem.downloadSections.isNotBlank()){
|
||||
downloadItem.downloadSections.split(";").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){
|
||||
DownloadViewModel.Type.audio -> {
|
||||
request.addOption("-x")
|
||||
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"
|
||||
|
||||
if (audioQualityId.isNotBlank()){
|
||||
|
|
@ -141,18 +144,33 @@ class DownloadWorker(
|
|||
|
||||
val ext = downloadItem.format.container
|
||||
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")
|
||||
|
||||
if (downloadItem.audioPreferences.embedThumb) {
|
||||
request.addOption("--embed-thumbnail")
|
||||
request.addOption("--convert-thumbnails", "png")
|
||||
request.addOption("--convert-thumbnails", "jpg")
|
||||
try {
|
||||
val config = File(context.cacheDir.absolutePath + "/downloads/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
|
||||
val configData =
|
||||
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||
val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||
config.writeText(configData)
|
||||
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
||||
request.addOption("--config", config.absolutePath)
|
||||
} catch (ignored: Exception) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
android:checkable="true"
|
||||
app:strokeWidth="0dp"
|
||||
app:cardPreventCornerOverlap="true"
|
||||
android:layout_margin="10dp">
|
||||
android:layout_margin="20dp">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/image_view"
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@
|
|||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/download_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
<include layout="@layout/history_no_results"
|
||||
|
|
|
|||
|
|
@ -87,7 +87,16 @@
|
|||
android:layout_width="match_parent"
|
||||
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>
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/suggested_cuts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.533"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
@ -119,6 +119,43 @@
|
|||
|
||||
</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
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -127,7 +164,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearLayout5"
|
||||
app:layout_constraintTop_toBottomOf="@+id/suggested_cuts"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
>
|
||||
|
||||
|
|
@ -180,6 +217,17 @@
|
|||
app:layout_constraintStart_toStartOf="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
|
||||
android:id="@+id/new_cut"
|
||||
|
|
|
|||
|
|
@ -105,6 +105,18 @@
|
|||
android:id="@+id/download_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
android:layout_width="0dp"
|
||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:checkable="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
android:clickable="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="5dp"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:focusable="true">
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:scrollbars="none"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
|
|
@ -20,7 +19,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:padding="10dp"
|
||||
android:hint="@string/title"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||
|
||||
|
|
@ -35,7 +34,7 @@
|
|||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="10dp"
|
||||
android:padding="10dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
|
|
@ -80,13 +79,16 @@
|
|||
android:id="@+id/audio_quality_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text="@string/audio_quality" />
|
||||
<include layout="@layout/format_item" />
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/outputPath"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="0dp"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -102,8 +104,7 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/freespace"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="5dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@android:color/tab_indicator_text"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -112,7 +113,7 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/adjust_audio"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingVertical="10dp"
|
||||
android:padding="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
|
@ -205,22 +206,6 @@
|
|||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
</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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -111,21 +111,6 @@
|
|||
android:text="@string/edit_selected"
|
||||
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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
|
|
@ -20,7 +19,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:hint="@string/title"
|
||||
android:paddingBottom="10dp">
|
||||
android:padding="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -33,7 +32,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="10dp">
|
||||
android:padding="10dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/author_textinput"
|
||||
|
|
@ -74,6 +73,7 @@
|
|||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text="@string/video_quality" />
|
||||
|
||||
<include layout="@layout/format_item" />
|
||||
|
|
@ -85,7 +85,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/save_dir"
|
||||
android:paddingTop="10dp">
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="0dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -97,8 +99,7 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/freespace"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="5dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:textSize="13sp"
|
||||
android:textColor="@android:color/tab_indicator_text"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -110,7 +111,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingVertical="10dp">
|
||||
android:padding="10dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -213,24 +214,6 @@
|
|||
|
||||
</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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/queries"
|
||||
android:layout_margin="10dp"
|
||||
app:chipSpacingVertical="-10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@
|
|||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/shortcutsChipGroup"
|
||||
android:layout_width="wrap_content"
|
||||
app:chipSpacingVertical="0dp"
|
||||
app:chipSpacingVertical="-10dp"
|
||||
app:chipSpacing="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleLine="false">
|
||||
|
||||
|
|
|
|||
|
|
@ -192,4 +192,7 @@
|
|||
<string name="ignore_battery_optimization">Ignore Battery Optimization</string>
|
||||
<string name="cut">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>
|
||||
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
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
|
|
|
|||
Loading…
Reference in a new issue