1.7.1
This commit is contained in:
parent
f2077df2c9
commit
461d4679ac
28 changed files with 919 additions and 529 deletions
|
|
@ -10,7 +10,7 @@ plugins {
|
|||
def properties = new Properties()
|
||||
def versionMajor = 1
|
||||
def versionMinor = 7
|
||||
def versionPatch = 0
|
||||
def versionPatch = 1
|
||||
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
|
||||
def versionExt = ""
|
||||
|
||||
|
|
@ -189,6 +189,6 @@ dependencies {
|
|||
implementation "com.anggrayudi:storage:1.5.5"
|
||||
implementation 'me.zhanghai.android.fastscroll:library:1.3.0'
|
||||
implementation 'com.google.accompanist:accompanist-webview:0.30.1'
|
||||
implementation 'androidx.compose.material3:material3-android:1.2.0-alpha10'
|
||||
implementation 'androidx.compose.material3:material3-android:1.2.0-beta01'
|
||||
implementation "io.noties.markwon:core:4.6.2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,12 +240,14 @@ class MainActivity : BaseActivity() {
|
|||
|
||||
if (preferences.getBoolean("auto_update_ytdlp", false)){
|
||||
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||
if(DBManager.getInstance(this@MainActivity).downloadDao.getDownloadsCountByStatus(listOf("Active", "Queued")) == 0){
|
||||
if (UpdateUtil(this@MainActivity).updateYoutubeDL() == YoutubeDL.UpdateStatus.DONE) {
|
||||
val version = YoutubeDL.getInstance().version(context)
|
||||
Snackbar.make(findViewById(android.R.id.content),
|
||||
this@MainActivity.getString(R.string.ytld_update_success) + " [${version}]",
|
||||
Snackbar.LENGTH_LONG).show()
|
||||
kotlin.runCatching {
|
||||
if(DBManager.getInstance(this@MainActivity).downloadDao.getDownloadsCountByStatus(listOf("Active", "Queued")) == 0){
|
||||
if (UpdateUtil(this@MainActivity).updateYoutubeDL() == YoutubeDL.UpdateStatus.DONE) {
|
||||
val version = YoutubeDL.getInstance().version(context)
|
||||
Snackbar.make(findViewById(android.R.id.content),
|
||||
this@MainActivity.getString(R.string.ytld_update_success) + " [${version}]",
|
||||
Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
package com.deniscerri.ytdlnis.database.viewmodel
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.app.ActivityManager.RunningAppProcessInfo
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Log
|
||||
import android.util.Patterns
|
||||
import android.view.View
|
||||
import androidx.compose.material3.formatWithSkeleton
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.deniscerri.ytdlnis.App
|
||||
import com.deniscerri.ytdlnis.R
|
||||
|
|
@ -21,10 +19,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
|||
import com.deniscerri.ytdlnis.database.models.SearchHistoryItem
|
||||
import com.deniscerri.ytdlnis.database.repository.ResultRepository
|
||||
import com.deniscerri.ytdlnis.database.repository.SearchHistoryRepository
|
||||
import com.deniscerri.ytdlnis.receiver.ShareActivity
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadAudioFragment
|
||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadVideoFragment
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -34,12 +30,14 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ResultViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
class ResultViewModel(private val application: Application) : AndroidViewModel(application) {
|
||||
private val tag: String = "ResultViewModel"
|
||||
val repository : ResultRepository
|
||||
private val searchHistoryRepository : SearchHistoryRepository
|
||||
val items : LiveData<List<ResultItem>>
|
||||
private val infoUtil: InfoUtil
|
||||
private val notificationUtil: NotificationUtil
|
||||
data class ResultsUiState(
|
||||
var processing: Boolean,
|
||||
var errorMessage: Pair<Int, String>?,
|
||||
|
|
@ -64,6 +62,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
items = repository.allResults.asLiveData()
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)
|
||||
infoUtil = InfoUtil(application)
|
||||
notificationUtil = NotificationUtil(application)
|
||||
}
|
||||
|
||||
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
|
||||
|
|
@ -117,11 +116,23 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
|
||||
}
|
||||
}
|
||||
if (!isForegrounded()){
|
||||
notificationUtil.showQueriesFinished()
|
||||
}
|
||||
uiState.update {it.copy(processing = false)}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
private fun isForegrounded(): Boolean {
|
||||
return kotlin.runCatching {
|
||||
val appProcessInfo = RunningAppProcessInfo()
|
||||
ActivityManager.getMyMemoryState(appProcessInfo)
|
||||
appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND ||
|
||||
appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE
|
||||
}.getOrElse { true }
|
||||
}
|
||||
|
||||
private fun getQueryType(inputQuery: String) : String {
|
||||
var type = "Search"
|
||||
val p = Pattern.compile("(^(https?)://(www.)?youtu(.be)?)|(^(https?)://(www.)?piped.video)")
|
||||
|
|
@ -201,14 +212,14 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
updatingData.emit(false)
|
||||
updateResultData.emit(result)
|
||||
}
|
||||
}
|
||||
|
||||
updateResultDataJob?.start()
|
||||
updateResultDataJob?.invokeOnCompletion {
|
||||
if (it != null){
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
updatingData.emit(false)
|
||||
updateResultData.emit(mutableListOf())
|
||||
updateResultDataJob?.start()
|
||||
updateResultDataJob?.invokeOnCompletion {
|
||||
if (it != null){
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
updatingData.emit(false)
|
||||
updateResultData.emit(mutableListOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -230,15 +241,31 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
if (updateFormatsResultDataJob == null || updateFormatsResultDataJob?.isCancelled == true || updateFormatsResultDataJob?.isCompleted == true) {
|
||||
updateFormatsResultDataJob = viewModelScope.launch(Dispatchers.IO) {
|
||||
updatingFormats.emit(true)
|
||||
val formats = infoUtil.getFormats(result.url)
|
||||
updatingFormats.emit(false)
|
||||
if (formats.isNotEmpty() && isActive) {
|
||||
getItemByURL(result.url)?.apply {
|
||||
this.formats = formats.toMutableList()
|
||||
update(this)
|
||||
val formats = kotlin.runCatching {
|
||||
infoUtil.getFormats(result.url)
|
||||
}.onFailure { e ->
|
||||
if (e !is kotlinx.coroutines.CancellationException){
|
||||
uiState.update {it.copy(
|
||||
processing = false,
|
||||
errorMessage = Pair(R.string.no_results, e.message.toString()),
|
||||
actions = mutableListOf(Pair(R.string.copy_log, ResultAction.COPY_LOG))
|
||||
)}
|
||||
Log.e(tag, e.toString())
|
||||
}
|
||||
}.getOrNull()
|
||||
|
||||
updatingFormats.emit(false)
|
||||
|
||||
formats?.apply {
|
||||
if (formats.isNotEmpty() && isActive) {
|
||||
getItemByURL(result.url)?.apply {
|
||||
this.formats = formats.toMutableList()
|
||||
update(this)
|
||||
}
|
||||
updateFormatsResultData.emit(formats.toMutableList())
|
||||
}
|
||||
updateFormatsResultData.emit(formats.toMutableList())
|
||||
}
|
||||
|
||||
}
|
||||
updateFormatsResultDataJob?.start()
|
||||
updateFormatsResultDataJob?.invokeOnCompletion {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.graphics.ColorMatrix
|
|||
import android.graphics.ColorMatrixColorFilter
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
|
@ -22,7 +23,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.squareup.picasso.Picasso
|
||||
|
|
@ -89,13 +89,12 @@ class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activit
|
|||
itemTitle.text = title
|
||||
|
||||
// Bottom Info ----------------------------------
|
||||
val bottomInfo = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||
var info = item.author
|
||||
if (item.duration.isNotEmpty()) {
|
||||
if (item.author.isNotEmpty()) info += " • "
|
||||
info += item.duration
|
||||
}
|
||||
bottomInfo.text = info
|
||||
val author = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||
author.text = item.author
|
||||
|
||||
val length = card.findViewById<TextView>(R.id.length)
|
||||
length.text = item.duration
|
||||
|
||||
|
||||
// TIME DOWNLOADED ----------------------------------
|
||||
val datetime = card.findViewById<TextView>(R.id.downloads_info_time)
|
||||
|
|
@ -122,9 +121,14 @@ class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activit
|
|||
}
|
||||
})
|
||||
thumbnail.alpha = 0.7f
|
||||
btn.backgroundTintList = ContextCompat.getColorStateList(activity, R.color.black)
|
||||
btn.imageTintList = ContextCompat.getColorStateList(activity, R.color.white)
|
||||
}
|
||||
|
||||
if (item.type == DownloadViewModel.Type.audio) {
|
||||
if (filePresent) btn.setImageResource(R.drawable.ic_music_downloaded) else btn.setImageResource(R.drawable.ic_music)
|
||||
if (filePresent) btn.setImageResource(R.drawable.ic_music_downloaded) else {
|
||||
btn.setImageResource(R.drawable.ic_music)
|
||||
}
|
||||
} else if (item.type == DownloadViewModel.Type.video) {
|
||||
if (filePresent) btn.setImageResource(R.drawable.ic_video_downloaded) else btn.setImageResource(R.drawable.ic_video)
|
||||
}else{
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
|
|||
private lateinit var newCutBtn : Button
|
||||
private lateinit var resetBtn : Button
|
||||
private lateinit var chipGroup : ChipGroup
|
||||
private lateinit var suggestedLabel : View
|
||||
|
||||
private var timeSeconds by Delegates.notNull<Int>()
|
||||
private lateinit var selectedCuts: MutableList<String>
|
||||
|
|
@ -127,6 +128,7 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
|
|||
okBtn = view.findViewById(R.id.okButton)
|
||||
suggestedChips = view.findViewById(R.id.chapters)
|
||||
suggestedChapters = view.findViewById(R.id.suggested_cuts)
|
||||
suggestedLabel = view.findViewById(R.id.suggestedLabel)
|
||||
|
||||
|
||||
//cut list section
|
||||
|
|
@ -451,6 +453,12 @@ class CutVideoBottomSheetDialog(private val item: DownloadItem, private val urls
|
|||
cutListSection.visibility = View.GONE
|
||||
rangeSlider.setValues(0F, 100F)
|
||||
player.seekTo(0)
|
||||
suggestedChips.children.apply {
|
||||
this.forEach {
|
||||
it.isVisible = ! selectedCuts.contains((it as Chip).text)
|
||||
}
|
||||
suggestedLabel.isVisible = this.any { it.isVisible }
|
||||
}
|
||||
}
|
||||
|
||||
resetBtn.setOnClickListener {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import com.google.android.material.progressindicator.LinearProgressIndicator
|
|||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.android.material.textfield.TextInputLayout.END_ICON_NONE
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
|
@ -69,8 +70,8 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
): View? {
|
||||
fragmentView = inflater.inflate(R.layout.fragment_download_audio, container, false)
|
||||
activity = getActivity()
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
|
||||
infoUtil = InfoUtil(requireContext())
|
||||
genericAudioFormats = infoUtil.getGenericAudioFormats(requireContext().resources)
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
|
@ -291,6 +292,13 @@ class DownloadAudioFragment(private var resultItem: ResultItem? = null, private
|
|||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||
}
|
||||
},
|
||||
updateDataClicked = {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
resultItem?.apply {
|
||||
resultViewModel.updateItemData(this)
|
||||
}
|
||||
}
|
||||
},
|
||||
extraCommandsClicked = {
|
||||
val callback = object : ExtraCommandsListener {
|
||||
override fun onChangeExtraCommand(c: String) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.core.view.isVisible
|
|||
import androidx.fragment.app.commit
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.Player.Command
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -34,6 +35,7 @@ import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
|
|||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel.Type
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
|
||||
|
|
@ -47,6 +49,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -69,7 +72,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
private lateinit var historyViewModel: HistoryViewModel
|
||||
private lateinit var resultViewModel: ResultViewModel
|
||||
private lateinit var behavior: BottomSheetBehavior<View>
|
||||
private lateinit var commandTemplateDao : CommandTemplateDao
|
||||
private lateinit var commandTemplateViewModel : CommandTemplateViewModel
|
||||
private lateinit var infoUtil: InfoUtil
|
||||
private lateinit var sharedPreferences : SharedPreferences
|
||||
private lateinit var updateItem : Button
|
||||
|
|
@ -89,7 +92,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
|
||||
historyViewModel = ViewModelProvider(requireActivity())[HistoryViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
|
||||
commandTemplateDao = DBManager.getInstance(requireContext()).commandTemplateDao
|
||||
commandTemplateViewModel = ViewModelProvider(requireActivity())[CommandTemplateViewModel::class.java]
|
||||
infoUtil = InfoUtil(requireContext())
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
||||
|
|
@ -166,7 +169,7 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
var commandTemplateNr = 0
|
||||
lifecycleScope.launch{
|
||||
withContext(Dispatchers.IO){
|
||||
commandTemplateNr = commandTemplateDao.getTotalNumber()
|
||||
commandTemplateNr = commandTemplateViewModel.getTotalNumber()
|
||||
if (!Patterns.WEB_URL.matcher(result.url).matches()) commandTemplateNr++
|
||||
if(commandTemplateNr <= 0){
|
||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
|
||||
|
|
@ -242,7 +245,16 @@ class DownloadBottomSheetDialog : BottomSheetDialogFragment() {
|
|||
override fun onTabSelected(tab: TabLayout.Tab?) {
|
||||
if (tab!!.position == 2 && commandTemplateNr == 0){
|
||||
tabLayout.selectTab(tabLayout.getTabAt(1))
|
||||
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||
val s = Snackbar.make(view, getString(R.string.add_template_first), Snackbar.LENGTH_LONG)
|
||||
s.setAction(R.string.new_template){
|
||||
UiUtil.showCommandTemplateCreationOrUpdatingSheet(item = null, context = requireActivity(), lifeCycle = this@DownloadBottomSheetDialog, commandTemplateViewModel = commandTemplateViewModel){
|
||||
commandTemplateNr = 1
|
||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.isClickable = true
|
||||
(tabLayout.getChildAt(0) as? ViewGroup)?.getChildAt(2)?.alpha = 1f
|
||||
tabLayout.selectTab(tabLayout.getTabAt(2))
|
||||
}
|
||||
}
|
||||
s.show()
|
||||
}else if (tab.position == 1 && isAudioOnly){
|
||||
tabLayout.selectTab(tabLayout.getTabAt(0))
|
||||
Toast.makeText(context, getString(R.string.audio_only_item), Toast.LENGTH_SHORT).show()
|
||||
|
|
|
|||
|
|
@ -455,6 +455,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
bottomSheet.dismiss()
|
||||
},
|
||||
cutClicked = {},
|
||||
updateDataClicked = {},
|
||||
extraCommandsClicked = {
|
||||
val callback = object : ExtraCommandsListener {
|
||||
override fun onChangeExtraCommand(c: String) {
|
||||
|
|
@ -509,6 +510,7 @@ class DownloadMultipleBottomSheetDialog : BottomSheetDialogFragment(), Configure
|
|||
bottomSheet.dismiss()
|
||||
},
|
||||
cutClicked = {},
|
||||
updateDataClicked = {},
|
||||
filenameTemplateSet = { checked ->
|
||||
items.forEach { it.customFileNameTemplate = checked }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@ import com.google.android.material.textfield.TextInputLayout.END_ICON_CUSTOM
|
|||
import com.google.android.material.textfield.TextInputLayout.END_ICON_NONE
|
||||
import com.google.android.material.textfield.TextInputLayout.EndIconMode
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -72,8 +74,8 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
): View? {
|
||||
fragmentView = inflater.inflate(R.layout.fragment_download_video, container, false)
|
||||
activity = getActivity()
|
||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(this@DownloadVideoFragment)[ResultViewModel::class.java]
|
||||
downloadViewModel = ViewModelProvider(requireActivity())[DownloadViewModel::class.java]
|
||||
resultViewModel = ViewModelProvider(requireActivity())[ResultViewModel::class.java]
|
||||
infoUtil = InfoUtil(requireContext())
|
||||
genericVideoFormats = infoUtil.getGenericVideoFormats(requireContext().resources)
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||
|
|
@ -310,6 +312,13 @@ class DownloadVideoFragment(private var resultItem: ResultItem? = null, private
|
|||
bottomSheet.show(parentFragmentManager, "cutVideoSheet")
|
||||
}
|
||||
},
|
||||
updateDataClicked = {
|
||||
CoroutineScope(SupervisorJob()).launch(Dispatchers.IO) {
|
||||
resultItem?.apply {
|
||||
resultViewModel.updateItemData(this)
|
||||
}
|
||||
}
|
||||
},
|
||||
filenameTemplateSet = {
|
||||
downloadItem.customFileNameTemplate = it
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.*
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
|
|
@ -45,6 +46,7 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
|||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdlnis.util.Extensions.setFullScreen
|
||||
import com.deniscerri.ytdlnis.util.FileUtil
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||
|
|
@ -126,11 +128,7 @@ class ResultCardDetailsDialog : BottomSheetDialogFragment(), GenericDownloadAdap
|
|||
val displayMetrics = DisplayMetrics()
|
||||
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
|
||||
if(resources.getBoolean(R.bool.isTablet) || resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE){
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.peekHeight = displayMetrics.heightPixels
|
||||
}
|
||||
if (!resources.getBoolean(R.bool.isTablet) && resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE){
|
||||
behavior.maxWidth = displayMetrics.widthPixels
|
||||
dialog.setFullScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package com.deniscerri.ytdlnis.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.graphics.Outline
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.graphics.drawable.shapes.OvalShape
|
||||
import android.media.MediaMetadataRetriever
|
||||
|
|
@ -12,13 +14,23 @@ import android.net.Uri
|
|||
import android.util.DisplayMetrics
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewOutlineProvider
|
||||
import android.widget.EditText
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.Px
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.whenStarted
|
||||
import androidx.lifecycle.withStarted
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.neo.highlight.core.Highlight
|
||||
import com.neo.highlight.util.listener.HighlightTextWatcher
|
||||
import com.neo.highlight.util.scheme.ColorScheme
|
||||
import kotlinx.coroutines.launch
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
|
@ -109,4 +121,41 @@ object Extensions {
|
|||
duration?.toIntOrNull()?.div(1000) ?: 0
|
||||
}.getOrElse { 0 }
|
||||
}
|
||||
|
||||
|
||||
fun Dialog.setFullScreen(
|
||||
@Px cornerRadius: Int = 0,
|
||||
skipCollapsed: Boolean = true
|
||||
) {
|
||||
check(this is BottomSheetDialog) {
|
||||
"Dialog must be a BottomSheetBottomSheetDialog."
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
withStarted {
|
||||
val bottomSheetLayout = findViewById<ViewGroup>(com.google.android.material.R.id.design_bottom_sheet) ?: return@withStarted
|
||||
with(bottomSheetLayout) {
|
||||
updateLayoutParams {
|
||||
height = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
clipToOutline = true
|
||||
outlineProvider = object : ViewOutlineProvider() {
|
||||
override fun getOutline(view: View, outline: Outline) {
|
||||
outline.setRoundRect(
|
||||
0,
|
||||
0,
|
||||
view.width,
|
||||
view.height + cornerRadius,
|
||||
cornerRadius.toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
behavior.maxWidth = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
behavior.skipCollapsed = skipCollapsed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.deniscerri.ytdlnis.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Resources
|
||||
|
|
@ -553,6 +554,7 @@ class InfoUtil(private val context: Context) {
|
|||
urlsFile.delete()
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun getFromYTDL(query: String): ArrayList<ResultItem?> {
|
||||
val items = arrayListOf<ResultItem?>()
|
||||
val searchEngine = sharedPreferences.getString("search_engine", "ytsearch")
|
||||
|
|
@ -978,6 +980,7 @@ class InfoUtil(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun buildYoutubeDLRequest(downloadItem: DownloadItem) : YoutubeDLRequest{
|
||||
val request = if (downloadItem.playlistURL.isNullOrBlank() || downloadItem.playlistTitle.isBlank() || downloadItem.playlistIndex == null){
|
||||
YoutubeDLRequest(downloadItem.url)
|
||||
|
|
@ -1108,15 +1111,14 @@ class InfoUtil(private val context: Context) {
|
|||
request.addOption("--force-keyframes-at-cuts")
|
||||
}
|
||||
}
|
||||
if (filenameTemplate.isBlank()){
|
||||
filenameTemplate = "%(section_title& {}|)s %(title)s"
|
||||
filenameTemplate = if (filenameTemplate.isBlank()){
|
||||
"%(section_title& {}|)s%(title)s"
|
||||
}else{
|
||||
filenameTemplate += " %(section_title& {}|)s "
|
||||
"%(section_title& {}|)s$filenameTemplate"
|
||||
}
|
||||
if (downloadItem.downloadSections.split(";").size > 1){
|
||||
filenameTemplate = "%(autonumber)d. %(section_start& {}|)s $filenameTemplate"
|
||||
filenameTemplate = "%(autonumber)d. %(section_start>%H:%M:%S)s $filenameTemplate"
|
||||
}
|
||||
request.addOption("--output-na-placeholder", " ")
|
||||
}
|
||||
|
||||
if (sharedPreferences.getBoolean("use_audio_quality", false)){
|
||||
|
|
@ -1163,7 +1165,7 @@ class InfoUtil(private val context: Context) {
|
|||
if (audioQualityId.isBlank() || listOf("0", context.getString(R.string.best_quality), "ba", "best", "").contains(audioQualityId)){
|
||||
audioQualityId = ""
|
||||
}else if (listOf(context.getString(R.string.worst_quality), "wa", "worst").contains(audioQualityId)){
|
||||
audioQualityId = "worstaudio"
|
||||
audioQualityId = "wa/w"
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1224,7 +1226,7 @@ class InfoUtil(private val context: Context) {
|
|||
if (cropThumb){
|
||||
try {
|
||||
val config = File(context.cacheDir.absolutePath + "/config" + downloadItem.id + "##ffmpegCrop.txt")
|
||||
val configData = "--ppa \"ffmpeg: -c:v mjpeg -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)
|
||||
|
|
@ -1296,7 +1298,8 @@ class InfoUtil(private val context: Context) {
|
|||
if (videoF == context.resources.getString(R.string.best_quality) || videoF == "best") {
|
||||
videoF = "bv"
|
||||
}else if (videoF == context.resources.getString(R.string.worst_quality) || videoF == "worst") {
|
||||
videoF = "worst"
|
||||
videoF = "wv"
|
||||
if (audioF == "ba") audioF = "wa"
|
||||
}else if (defaultFormats.contains(videoF)) {
|
||||
videoF = "bv[height<="+videoF.split("_")[0].dropLast(1)+"]"
|
||||
}
|
||||
|
|
@ -1316,7 +1319,7 @@ class InfoUtil(private val context: Context) {
|
|||
.filter { it.isNotBlank() }
|
||||
.ifEmpty {
|
||||
val list = mutableListOf<String>()
|
||||
if (preferredAudioLanguage.isNotEmpty()) list.add("ba[language^=$preferredAudioLanguage]")
|
||||
if (preferredAudioLanguage.isNotEmpty() && !downloadItem.videoPreferences.removeAudio) list.add("ba[language^=$preferredAudioLanguage]")
|
||||
list.add(audioF)
|
||||
list
|
||||
}.apply {
|
||||
|
|
@ -1346,7 +1349,7 @@ class InfoUtil(private val context: Context) {
|
|||
if (!f.contains(al)) f.append(al)
|
||||
}
|
||||
//build format with best audio
|
||||
if (!f.contains("$v+ba/")) f.append("$v+ba/")
|
||||
if (!f.contains("$v+ba/") && !f.contains("wa")) f.append("$v+ba/")
|
||||
//build format with standalone video
|
||||
f.append("$v/")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,6 +549,31 @@ class NotificationUtil(var context: Context) {
|
|||
notificationManager.notify(FORMAT_UPDATING_FINISHED_NOTIFICATION_ID, notificationBuilder.build())
|
||||
}
|
||||
|
||||
fun showQueriesFinished() {
|
||||
val notificationBuilder = getBuilder(DOWNLOAD_FINISHED_CHANNEL_ID)
|
||||
|
||||
val openMultipleDownloads = NavDeepLinkBuilder(context)
|
||||
.setGraph(R.navigation.nav_graph)
|
||||
.setDestination(R.id.homeFragment)
|
||||
.createPendingIntent()
|
||||
|
||||
notificationBuilder
|
||||
.setContentTitle(resources.getString(R.string.finished_download_notification_channel_name))
|
||||
.setSmallIcon(R.drawable.ic_launcher_foreground_large)
|
||||
.setLargeIcon(
|
||||
BitmapFactory.decodeResource(
|
||||
resources,
|
||||
R.drawable.ic_launcher_foreground_large
|
||||
)
|
||||
)
|
||||
.setContentIntent(openMultipleDownloads)
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.clearActions()
|
||||
|
||||
notificationManager.notify(QUERY_PROCESS_FINISHED_NOTIFICATION_ID, notificationBuilder.build())
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DOWNLOAD_SERVICE_CHANNEL_ID = "1"
|
||||
const val COMMAND_DOWNLOAD_SERVICE_CHANNEL_ID = "2"
|
||||
|
|
@ -562,6 +587,7 @@ class NotificationUtil(var context: Context) {
|
|||
const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 50000
|
||||
const val DOWNLOAD_ERRORED_NOTIFICATION_ID = 60000
|
||||
const val FORMAT_UPDATING_FINISHED_NOTIFICATION_ID = 70000
|
||||
const val QUERY_PROCESS_FINISHED_NOTIFICATION_ID = 80000
|
||||
|
||||
private const val PROGRESS_MAX = 100
|
||||
private const val PROGRESS_CURR = 0
|
||||
|
|
|
|||
|
|
@ -29,10 +29,14 @@ import android.widget.Toast
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.compose.ui.text.font.Typeface
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
|
@ -896,6 +900,7 @@ object UiUtil {
|
|||
)
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun showSubtitleLanguagesDialog(context: Activity, currentValue: String, ok: (newValue: String) -> Unit){
|
||||
val builder = MaterialAlertDialogBuilder(context)
|
||||
builder.setTitle(context.getString(R.string.subtitle_languages))
|
||||
|
|
@ -1073,7 +1078,8 @@ object UiUtil {
|
|||
saveSubtitlesClicked: (Boolean) -> Unit,
|
||||
subtitleLanguagesSet: (String) -> Unit,
|
||||
removeAudioClicked: (Boolean) -> Unit,
|
||||
extraCommandsClicked: () -> Unit
|
||||
extraCommandsClicked: () -> Unit,
|
||||
updateDataClicked: () -> Unit
|
||||
){
|
||||
val embedSubs = view.findViewById<Chip>(R.id.embed_subtitles)
|
||||
val saveSubtitles = view.findViewById<Chip>(R.id.save_subtitles)
|
||||
|
|
@ -1162,7 +1168,7 @@ object UiUtil {
|
|||
else{
|
||||
if(items[0].duration.isNotEmpty()){
|
||||
val downloadItem = items[0]
|
||||
cut.isEnabled = true
|
||||
cut.alpha = 1f
|
||||
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
||||
val cutVideoListener = object : VideoCutListener {
|
||||
|
||||
|
|
@ -1198,7 +1204,14 @@ object UiUtil {
|
|||
cutClicked(cutVideoListener)
|
||||
}
|
||||
}else{
|
||||
cut.isEnabled = false
|
||||
cut.alpha = 0.3f
|
||||
cut.setOnClickListener {
|
||||
val snack = Snackbar.make(view, context.getString(R.string.cut_unavailable), Snackbar.LENGTH_SHORT)
|
||||
snack.setAction(R.string.update){
|
||||
updateDataClicked()
|
||||
}
|
||||
snack.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1268,7 +1281,7 @@ object UiUtil {
|
|||
sponsorBlockItemsSet: (Array<String>, List<Boolean>) -> Unit,
|
||||
cutClicked: (VideoCutListener) -> Unit,
|
||||
extraCommandsClicked: () -> Unit,
|
||||
|
||||
updateDataClicked: () -> Unit
|
||||
){
|
||||
val embedThumb = view.findViewById<Chip>(R.id.embed_thumb)
|
||||
val cropThumb = view.findViewById<Chip>(R.id.crop_thumb)
|
||||
|
|
@ -1351,7 +1364,7 @@ object UiUtil {
|
|||
else{
|
||||
val downloadItem = items[0]
|
||||
if (downloadItem.duration.isNotEmpty()){
|
||||
cut.isEnabled = true
|
||||
cut.alpha = 1f
|
||||
if (downloadItem.downloadSections.isNotBlank()) cut.text = downloadItem.downloadSections
|
||||
val cutVideoListener = object : VideoCutListener {
|
||||
override fun onChangeCut(list: List<String>) {
|
||||
|
|
@ -1379,7 +1392,14 @@ object UiUtil {
|
|||
}
|
||||
|
||||
}else{
|
||||
cut.isEnabled = false
|
||||
cut.alpha = 0.3f
|
||||
cut.setOnClickListener {
|
||||
val snack = Snackbar.make(view, context.getString(R.string.cut_unavailable), Snackbar.LENGTH_SHORT)
|
||||
snack.setAction(R.string.update){
|
||||
updateDataClicked()
|
||||
}
|
||||
snack.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1632,6 +1652,7 @@ object UiUtil {
|
|||
deleteDialog.show()
|
||||
}
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
fun showFilenameTemplateDialog(context: Activity, currentFilename: String, dialogTitle: String = context.getString(R.string.file_name_template), filenameSelected: (f: String) -> Unit){
|
||||
val builder = MaterialAlertDialogBuilder(context)
|
||||
builder.setTitle(dialogTitle)
|
||||
|
|
@ -1783,11 +1804,13 @@ object UiUtil {
|
|||
val builder = MaterialAlertDialogBuilder(context)
|
||||
builder.setTitle(context.getString(R.string.command))
|
||||
val view = context.layoutInflater.inflate(R.layout.command_dialog, null)
|
||||
val text = view.findViewById<TextView>(R.id.commandText)
|
||||
text.text = command
|
||||
text.isLongClickable = true
|
||||
text.setTextIsSelectable(true)
|
||||
text.enableTextHighlight()
|
||||
view.findViewById<TextView>(R.id.commandText).apply {
|
||||
text = command
|
||||
isLongClickable = true
|
||||
setTextIsSelectable(true)
|
||||
enableTextHighlight()
|
||||
setPadding(20, 0, 20, 0)
|
||||
}
|
||||
|
||||
builder.setView(view)
|
||||
builder.setPositiveButton(
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import androidx.preference.PreferenceManager
|
|||
import com.deniscerri.ytdlnis.BuildConfig
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.models.GithubRelease
|
||||
import com.deniscerri.ytdlnis.util.Extensions.enableFastScroll
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
|
|
@ -38,7 +37,9 @@ import com.yausername.youtubedl_android.YoutubeDL.UpdateStatus
|
|||
import io.noties.markwon.AbstractMarkwonPlugin
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.MarkwonConfiguration
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
|
|
@ -122,7 +123,8 @@ class UpdateUtil(var context: Context) {
|
|||
)
|
||||
.setAllowedOverRoaming(true)
|
||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
.setTitle(context.getString(R.string.downloading_update))
|
||||
.setTitle(releaseVersion.name)
|
||||
.setDescription(context.getString(R.string.downloading_update))
|
||||
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, releaseVersion.name)
|
||||
)
|
||||
|
||||
|
|
@ -176,42 +178,7 @@ class UpdateUtil(var context: Context) {
|
|||
layoutParams.setMargins(20, 20, 20, 0)
|
||||
scrollView.layoutParams = layoutParams
|
||||
scrollView.addView(linearLayout)
|
||||
|
||||
getGithubReleases().forEach {
|
||||
(activity.layoutInflater.inflate(R.layout.changelog_item, null) as MaterialCardView).apply {
|
||||
this.layoutParams = layoutParams
|
||||
findViewById<TextView>(R.id.version).text = it.tag_name
|
||||
findViewById<TextView>(R.id.date).text = SimpleDateFormat(
|
||||
DateFormat.getBestDateTimePattern(
|
||||
Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(it.published_at.time)
|
||||
|
||||
val mdText = findViewById<TextView>(R.id.content)
|
||||
val mw = Markwon.builder(context).usePlugin(object: AbstractMarkwonPlugin() {
|
||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||
builder.linkResolver { view, link ->
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
|
||||
startActivity(context, browserIntent, Bundle())
|
||||
}
|
||||
}
|
||||
}).build()
|
||||
mw.setMarkdown(mdText, it.body)
|
||||
|
||||
|
||||
val assetGroup = findViewById<ChipGroup>(R.id.assets)
|
||||
it.assets.forEachIndexed { idx, c ->
|
||||
val tmp = activity.layoutInflater.inflate(R.layout.suggestion_chip, assetGroup, false) as Chip
|
||||
tmp.text = c.name
|
||||
tmp.id = idx
|
||||
tmp.setOnClickListener {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(c.browser_download_url))
|
||||
startActivity(context, browserIntent, Bundle())
|
||||
}
|
||||
assetGroup!!.addView(tmp)
|
||||
}
|
||||
|
||||
linearLayout.addView(this)
|
||||
}
|
||||
}
|
||||
val releases = getGithubReleases()
|
||||
|
||||
val changeLogDialog = MaterialAlertDialogBuilder(context)
|
||||
.setTitle(activity.getString(R.string.changelog))
|
||||
|
|
@ -222,6 +189,46 @@ class UpdateUtil(var context: Context) {
|
|||
changeLogDialog.show()
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
releases.forEach {
|
||||
(activity.layoutInflater.inflate(R.layout.changelog_item, null) as MaterialCardView).apply {
|
||||
this.layoutParams = layoutParams
|
||||
findViewById<TextView>(R.id.version).text = it.tag_name
|
||||
findViewById<TextView>(R.id.date).text = SimpleDateFormat(
|
||||
DateFormat.getBestDateTimePattern(
|
||||
Locale.getDefault(), "ddMMMyyyy - HHmm"), Locale.getDefault()).format(it.published_at.time)
|
||||
|
||||
val mdText = findViewById<TextView>(R.id.content)
|
||||
val mw = Markwon.builder(context).usePlugin(object: AbstractMarkwonPlugin() {
|
||||
override fun configureConfiguration(builder: MarkwonConfiguration.Builder) {
|
||||
builder.linkResolver { view, link ->
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(link))
|
||||
startActivity(context, browserIntent, Bundle())
|
||||
}
|
||||
}
|
||||
}).build()
|
||||
mw.setMarkdown(mdText, it.body)
|
||||
|
||||
|
||||
val assetGroup = findViewById<ChipGroup>(R.id.assets)
|
||||
it.assets.forEachIndexed { idx, c ->
|
||||
val tmp = activity.layoutInflater.inflate(R.layout.suggestion_chip, assetGroup, false) as Chip
|
||||
tmp.text = c.name
|
||||
tmp.id = idx
|
||||
tmp.setOnClickListener {
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(c.browser_download_url))
|
||||
startActivity(context, browserIntent, Bundle())
|
||||
}
|
||||
assetGroup!!.addView(tmp)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main){
|
||||
linearLayout.addView(this@apply)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.onFailure {
|
||||
if (it.message != null){
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
|
|
|
|||
5
app/src/main/res/drawable/chipgroup_roundedcorner.xml
Normal file
5
app/src/main/res/drawable/chipgroup_roundedcorner.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="?attr/colorSurfaceContainerLow"/>
|
||||
<corners android:topLeftRadius="20dp" />
|
||||
</shape>
|
||||
|
|
@ -3,114 +3,129 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="20dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/frame_layout"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/player_constraint"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintWidth_percent=".5"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/info"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:resize_mode="fixed_height"
|
||||
app:useDefaultControls="true"
|
||||
app:use_controller="true" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_thumb"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_image"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:layout_constraintTop_toTopOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="@+id/frame_layout" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:singleLine="false"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="17sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/frame_layout" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_info"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
android:singleLine="false"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintWidth_default="percent"
|
||||
app:layout_constraintWidth_percent=".67">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/frame_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_music"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||
android:layout_width="55dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
app:icon="@drawable/ic_music"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_video"
|
||||
app:layout_constraintTop_toBottomOf="@id/frame_layout" />
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:resize_mode="fixed_height"
|
||||
app:useDefaultControls="true"
|
||||
app:use_controller="true" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_video"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||
android:layout_width="55dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
app:icon="@drawable/ic_video"
|
||||
app:layout_constraintEnd_toEndOf="@id/frame_layout"
|
||||
app:layout_constraintTop_toBottomOf="@id/frame_layout" />
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_thumb"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_image"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:layout_constraintTop_toTopOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="@+id/frame_layout" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:singleLine="false"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="17sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||
app:layout_constraintHorizontal_bias="0.277"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/frame_layout" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_info"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
android:singleLine="false"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="12sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_music"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:icon="@drawable/ic_music"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_video"
|
||||
app:layout_constraintTop_toBottomOf="@id/frame_layout" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/download_video"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="55dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:icon="@drawable/ic_video"
|
||||
app:layout_constraintEnd_toEndOf="@id/frame_layout"
|
||||
app:layout_constraintTop_toBottomOf="@id/frame_layout" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bottom_sheet_link"
|
||||
style="@style/Widget.Material3.Button.TextButton.Icon"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="textStart"
|
||||
android:textSize="15sp"
|
||||
app:icon="@drawable/ic_link"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/download_music"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/bottom_sheet_link"
|
||||
style="@style/Widget.Material3.Button.TextButton.Icon"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:text="@string/app_name"
|
||||
android:textAlignment="textStart"
|
||||
android:textSize="15sp"
|
||||
app:icon="@drawable/ic_link"
|
||||
app:layout_constraintEnd_toStartOf="@+id/info"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/download_music" />
|
||||
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
|
@ -119,9 +134,8 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_marginHorizontal="10dp"
|
||||
android:scrollbars="none"
|
||||
app:layout_constraintWidth_percent=".5"
|
||||
app:layout_constraintVertical_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@id/frame_layout"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@id/player_constraint"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
|
|
|
|||
|
|
@ -1,334 +1,362 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<androidx.core.widget.NestedScrollView xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="20dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/frame_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
|
||||
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:resize_mode="fixed_height"
|
||||
app:useDefaultControls="true"
|
||||
app:use_controller="false" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:translationZ="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pause"
|
||||
android:visibility="gone"
|
||||
android:clickable="false"
|
||||
app:iconSize="50dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:icon="@drawable/exomedia_ic_play_arrow_white"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/rewind"
|
||||
android:clickable="false"
|
||||
app:iconSize="50dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:icon="@drawable/exomedia_ic_rewind_white"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mute"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_music"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="@+id/frame_layout" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/durationText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:background="#80000000"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:maxLines="1"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
android:scrollbars="none"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cut_section"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/frame_layout">
|
||||
android:paddingBottom="20dp"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/frame_layout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:layout_constraintDimensionRatio="H,16:9"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
|
||||
|
||||
<com.google.android.material.slider.RangeSlider
|
||||
android:id="@+id/rangeSlider"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
<androidx.media3.ui.PlayerView
|
||||
android:id="@+id/video_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:resize_mode="fixed_height"
|
||||
app:useDefaultControls="true"
|
||||
app:use_controller="false" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:translationZ="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:valueFrom="00.0"
|
||||
android:valueTo="100.0"
|
||||
app:labelBehavior="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:thumbRadius="0dp"
|
||||
app:trackHeight="20dp"
|
||||
app:values="@array/initial_slider_values" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pause"
|
||||
android:visibility="gone"
|
||||
android:clickable="false"
|
||||
app:iconSize="50dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:icon="@drawable/exomedia_ic_play_arrow_white"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/rewind"
|
||||
android:clickable="false"
|
||||
app:iconSize="50dp"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:icon="@drawable/exomedia_ic_rewind_white"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:indeterminate="true"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mute"
|
||||
style="@style/Widget.Material3.Button.IconButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_music"
|
||||
app:iconSize="30dp"
|
||||
app:iconTint="?android:colorAccent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintEnd_toEndOf="@+id/frame_layout" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout5"
|
||||
<TextView
|
||||
android:id="@+id/durationText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:background="#80000000"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLength="17"
|
||||
android:maxLines="1"
|
||||
android:minWidth="30dp"
|
||||
android:paddingHorizontal="5dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
app:cornerRadius="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/frame_layout"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cut_section"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toTopOf="@id/suggested_cuts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.533"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rangeSlider"
|
||||
app:layout_constraintVertical_bias="0.0">
|
||||
app:layout_constraintTop_toBottomOf="@+id/frame_layout">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/from_textinput"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
<com.google.android.material.slider.RangeSlider
|
||||
android:id="@+id/rangeSlider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/start">
|
||||
android:layout_marginVertical="10dp"
|
||||
android:valueFrom="00.0"
|
||||
android:valueTo="100.0"
|
||||
app:labelBehavior="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:thumbRadius="0dp"
|
||||
app:trackHeight="20dp"
|
||||
app:values="@array/initial_slider_values" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/colon"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout5"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text=":"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
android:layout_marginHorizontal="15dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toTopOf="@id/suggested_cuts"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.533"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/rangeSlider"
|
||||
app:layout_constraintVertical_bias="0.0">
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/to_textinput"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/end"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/colon">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/from_textinput"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
android:hint="@string/start">
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/colon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text=":"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/to_textinput"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/end"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/colon">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</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:id="@+id/suggestedLabel"
|
||||
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"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/suggested_cuts"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
app:icon="@drawable/ic_baseline_delete_outline_24"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/okButton"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cut"
|
||||
app:icon="@drawable/ic_check"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/suggested_cuts"
|
||||
android:id="@+id/list_section"
|
||||
android:visibility="gone"
|
||||
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"
|
||||
>
|
||||
android:paddingVertical="10dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/frame_layout"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/suggested" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:scrollbars="none"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
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"
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleLine="true" />
|
||||
android:layout_marginTop="4dp"
|
||||
android:maxLines="2"
|
||||
android:singleLine="false"
|
||||
android:text="@string/cut"
|
||||
android:textSize="25sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/new_cut"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</HorizontalScrollView>
|
||||
<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" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:id="@+id/new_cut"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="all"
|
||||
android:text="@string/new_cut"
|
||||
app:icon="@drawable/ic_cut"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginHorizontal="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/suggested_cuts"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
app:icon="@drawable/ic_baseline_delete_outline_24"/>
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/okButton"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cut"
|
||||
app:icon="@drawable/ic_check"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/cut_list_chip_group"
|
||||
android:paddingTop="10dp"
|
||||
app:chipSpacingVertical="-7dp"
|
||||
app:chipSpacingHorizontal="5dp"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/force_keyframes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:checked="true"
|
||||
android:textStyle="bold"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/force_keyframes"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/list_section"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/frame_layout"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:maxLines="2"
|
||||
android:singleLine="false"
|
||||
android:text="@string/cut"
|
||||
android:textSize="25sp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/new_cut"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
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"
|
||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="all"
|
||||
android:text="@string/new_cut"
|
||||
app:icon="@drawable/ic_cut"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/cut_list_chip_group"
|
||||
android:paddingTop="10dp"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/force_keyframes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:checked="true"
|
||||
android:textStyle="bold"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/force_keyframes"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
|
|
|||
|
|
@ -49,10 +49,11 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:maxLines="2"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:singleLine="false"
|
||||
android:text="@string/download"
|
||||
android:textSize="25sp"
|
||||
|
|
@ -84,9 +85,10 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/bottom_sheet_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:singleLine="false"
|
||||
android:text="@string/configure_download"
|
||||
android:textSize="12sp"
|
||||
|
|
|
|||
|
|
@ -37,36 +37,62 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_title"
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingTop="10dp"
|
||||
android:scrollbars="none"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowDx="4"
|
||||
android:shadowDy="4"
|
||||
android:shadowRadius="10"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/downloads_info_bottom"
|
||||
android:dividerPadding="5dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toTopOf="@+id/downloads_info_time"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:scrollbars="none"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowDx="4"
|
||||
android:shadowDy="4"
|
||||
android:shadowRadius="2"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_info_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="2"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:scrollbars="none"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowDx="4"
|
||||
android:shadowDy="4"
|
||||
android:shadowRadius="1.5"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="11sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_info_bottom"
|
||||
android:id="@+id/length"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="bottom"
|
||||
android:maxLines="1"
|
||||
android:padding="10dp"
|
||||
android:scrollbars="none"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowDx="4"
|
||||
|
|
@ -77,10 +103,8 @@
|
|||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloads_info_time"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/downloads_download_button_type" />
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloads_info_time"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/linearLayout2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toStartOf="@+id/download_button_type"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
<string-array name="video_formats">
|
||||
<item>@string/worst_quality</item>
|
||||
<item>240p</item>
|
||||
<item>360p</item>
|
||||
<item>480p</item>
|
||||
<item>720p</item>
|
||||
|
|
@ -48,6 +49,7 @@
|
|||
|
||||
<string-array name="video_formats_values">
|
||||
<item>worst</item>
|
||||
<item>240p_ytdlnisgeneric</item>
|
||||
<item>360p_ytdlnisgeneric</item>
|
||||
<item>480p_ytdlnisgeneric</item>
|
||||
<item>720p_ytdlnisgeneric</item>
|
||||
|
|
|
|||
|
|
@ -330,4 +330,5 @@
|
|||
<string name="changelog">Changelog</string>
|
||||
<string name="source">Source</string>
|
||||
<string name="app">App</string>
|
||||
<string name="cut_unavailable">You need to update the item data in order to be able to use cut feature</string>
|
||||
</resources>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
app:title="@string/auto_update_ytdlp" />
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="yt-dlp"
|
||||
android:defaultValue="piped"
|
||||
android:entries="@array/formats_source"
|
||||
android:entryValues="@array/formats_source_values"
|
||||
android:icon="@drawable/baseline_manage_search_24"
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ buildscript {
|
|||
commonsCompressVer = '1.12'
|
||||
youtubedlAndroidVer = "-SNAPSHOT"
|
||||
youtubedlAndroidVerNoPyCrypto = "97bee6c0e8"
|
||||
workVer = "2.8.1"
|
||||
workVer = "2.9.0"
|
||||
composeVer = '1.4.2'
|
||||
kotlinVer = "1.7.21"
|
||||
coroutineVer = '1.7.3'
|
||||
retrofitVer = "2.9.0"
|
||||
kodeinVer = "7.16.0"
|
||||
navVer = "2.7.5"
|
||||
media3_version = "1.1.1"
|
||||
navVer = "2.7.6"
|
||||
media3_version = "1.2.0"
|
||||
agp_version = '8.1.0'
|
||||
agp_version1 = '7.4.2'
|
||||
roomVer = '2.5.2'
|
||||
|
|
|
|||
79
fastlane/metadata/android/en-US/changelogs/10690.txt
Normal file
79
fastlane/metadata/android/en-US/changelogs/10690.txt
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
## What's New
|
||||
- removed trim filenames from command type downloads
|
||||
- fixed app not showing formats when it has generic formats
|
||||
- fixed author getting written as NA for kick videos
|
||||
- added separate channel for the worker notification that users can turn off
|
||||
- include search history when searching
|
||||
- removed scroll bug from command tab
|
||||
- added spacing between command template title and ok button in selection card
|
||||
- made download progress not dublicate in terminal
|
||||
- made ability to store terminal state
|
||||
- added ability to create multiple terminal instances and show them as a list similar to download queue
|
||||
- fixed thumbnail download not working
|
||||
- fixed app crashing when clicking on format updated notification
|
||||
- fixed app crashing when double clicking format on multiple download card
|
||||
- added custom sponsorblock api preference
|
||||
- removed contextual app bar when you its enabled and the user taps the log button in the erorred tab
|
||||
- made app always show quick download card and asynchoronously load data. Quick Download now if its on, it wont load data at all
|
||||
- added shimmer when loading data in the download card
|
||||
- fixed app showing no formats if there were no common formats. Now it will give you generic formats
|
||||
- made open command template list be half the screen, shortcuts third of the screen so the user can see what its being added
|
||||
- fixed sometimes app slipping queued downloads even though its told to pause all
|
||||
- fixed trim filenames cutting files too short
|
||||
- made mediastore scanning of files one by one
|
||||
- fixed filename template not working in multiple download card
|
||||
- fixed -F in terminal not being inline
|
||||
- added preferred audio codec
|
||||
- made auto update on boot if there are no active downloads
|
||||
- fixed format text overlapping
|
||||
- added a new error dialog in cases yt-dlp data fetching in the home screen fails. You can copy the log
|
||||
- formats auto updating as soon as the download card opens if auto-update is on
|
||||
- added preferred audio format always in the video tab
|
||||
- made app post downloads for queue in chunks
|
||||
- made app always save logs in case it fails, and if succeeds and logs are off it deletes it
|
||||
- fixed app navigating to home screen when cancelling download card in history screen
|
||||
- added a button to skip incoming app update so it wont bother you anymore
|
||||
- fixed settings not restoring some fields
|
||||
- fixed crunchyroll not working with cookies
|
||||
- added search for command templates
|
||||
- added sort filtering for command templates
|
||||
- added all shortcuts inside filename template creation dialog. Long click them to see the explanation
|
||||
- added preference to hide elements from the download card
|
||||
- made avc1 and m4a as preferred codecs for noobs
|
||||
- u can edit the duplicated download item right from the error dialog or access the history item to view the file
|
||||
- added extractor args lang when searching in yt-dlp
|
||||
- removed webarchive search engine since its not supported anymore
|
||||
- fixed terminal prematurely closing
|
||||
- made format auto-update on by default for new users
|
||||
- fixed main activity getting removed from recents when using the app with rvx
|
||||
- added ability to have the last used command template for the next download
|
||||
- fixed app crashing in landscape logs
|
||||
- fixed app constantly going back to home in landscape or config change. now it keeps state
|
||||
- add subtitle language suggestions in the subtitle dialog
|
||||
- made command template scroll state hold even if fragment is destroyed
|
||||
- added slovak sk language
|
||||
- fixed terminal icon being blank in white mode, and now its red
|
||||
- fixed share files from notification showing 2 files even though its 1
|
||||
- fixed history item not being deleted from the bottom sheet
|
||||
- cleared outdated player urls for stale result items
|
||||
- added export cookies as file
|
||||
- added export command templates for selected templates
|
||||
- added icons for history details sheet chips
|
||||
- added markdown in the update dialog
|
||||
- and other random bug fixes
|
||||
|
||||
## Autogenerated Changes
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/283
|
||||
* Create README-id.MD (Indonesian README) by @teddysulaimanGL in https://github.com/deniscerri/ytdlnis/pull/291
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/288
|
||||
* Update README-pt.md by @gigoloinc in https://github.com/deniscerri/ytdlnis/pull/293
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/292
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/301
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/305
|
||||
* Translations update from Hosted Weblate by @weblate in https://github.com/deniscerri/ytdlnis/pull/310
|
||||
|
||||
## New Contributors
|
||||
* @teddysulaimanGL made their first contribution in https://github.com/deniscerri/ytdlnis/pull/291
|
||||
* @gigoloinc made their first contribution in https://github.com/deniscerri/ytdlnis/pull/293
|
||||
|
||||
**Full Changelog**: https://github.com/deniscerri/ytdlnis/compare/v1.6.7...v1.6.8
|
||||
25
fastlane/metadata/android/en-US/changelogs/10700.txt
Normal file
25
fastlane/metadata/android/en-US/changelogs/10700.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
## What's New
|
||||
- Errored downloads sometimes had no title if it was quick downloaded. showed url instead
|
||||
- Fixed logs not being highlightable
|
||||
- Fixed app crashing when moving to landscape when having download card on
|
||||
- same thing for the details card
|
||||
- Fixed app crashing if you pressed download before data is loaded
|
||||
- Fixed app going to main activity when using rvx
|
||||
- Fixed errored downloads log button crashing the app
|
||||
- added hungarian
|
||||
- added serbian
|
||||
- added ability to enable/disable swipe gestures on any screen
|
||||
- added ability to choose whether extra command applies to audio video or both
|
||||
- hide search providers if the user has typed out an url in the searchview
|
||||
- fixed log removing some lines
|
||||
- added MASTER channel in yt-dlp updates
|
||||
- made errored downloads as a separate notification channel
|
||||
- fix notification language conflict for portugal brasil in worker notification
|
||||
- kept state of download card when going in landscape, even while updating data
|
||||
- add crop thumbnail to adjust audio preferences
|
||||
- fix command templates creation card showing extra command checkboxes even though extra command is disabled
|
||||
- fix preferred audio codec disrupting preferred audio id
|
||||
- made command tab sync title and author changes in the download item
|
||||
- fixed app duplicating --download-sections when spamming the extra commands page
|
||||
- added BUFFER SIZE as a preference in download settings
|
||||
- fixed prx series search engine not working
|
||||
31
fastlane/metadata/android/en-US/changelogs/10710.txt
Normal file
31
fastlane/metadata/android/en-US/changelogs/10710.txt
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
## What's New
|
||||
- fixed error notification not being dismissed and having a progress bar
|
||||
- fixed editing filename template not using multiple copies of the same tag and writing at the cursor
|
||||
- fixed appending search items in the search view not working for links
|
||||
- fixed terminal removing any instance of yt-dlp in the command instead of just the beginning
|
||||
- added ability to long press an item in the format details sheet to see the full string, and copy it/strings
|
||||
- ellipsised really long titles and authors in history/download details bottom sheet
|
||||
- now u can see all available piped instances in the piped instance dialog for you to choose
|
||||
- removed really long format command and replaced them with -S format sorting
|
||||
- fixed app not hiding adjust templates if user unchecked it
|
||||
- added ability to show the command that was used in a history item, u can also see that in a queued,cancelled ... download
|
||||
- Implemented preferred Audio Language. App will automatically choose an audio with your preference if it can find it, both in the download card also if you quick downloaded it
|
||||
- added subtitle language codes suggestions in the settings page
|
||||
- made the extractor chips in history page Sentence case
|
||||
- added a changelog screen where you can see recent releases and you can download the apks from it too
|
||||
- prevented app from crashing when trying to backup from a corrupted backup
|
||||
- added uploader_id as fallback for author data fetching in yt-dlp in case others are empty
|
||||
- fixed null pointer exception when running the update multiple items formats worker
|
||||
- added the seconds where the cut starts on downloads with cuts in them
|
||||
- made autonumbers be normal numbers instead of being 5 digits
|
||||
- fixed filename templates in cut files and added the index in the beginning and fixed bugs if the users left the template as empty
|
||||
- added 240p as a generic format
|
||||
|
||||
## Intent integration with the app
|
||||
You can use intents or apps like tasker or macrodroid to run commands to the app to run a download without user interaction
|
||||
Accepted variables:
|
||||
|
||||
TYPE -> it can be: audio,video,command
|
||||
BACKGROUND -> whether the app downloads on its own and wont show the download card if you have it on
|
||||
COMMAND -> if your preferred type is audio/video or you set the TYPE variable as so, this will be appended to your Extra Commands string. If the type is command, the whole command will be used for the download
|
||||
The intent that needs to be created is of android.intent.action.SEND and the intent text should be the url that you need to download.
|
||||
Loading…
Reference in a new issue