added stuff
added file picker for the sheet cancel title and author name sync between types sheet showing when there is one result trending not refreshing every time app shows
This commit is contained in:
parent
7f813ebd96
commit
92d6b2f197
27 changed files with 420 additions and 510 deletions
|
|
@ -167,7 +167,7 @@
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ dependencies {
|
||||||
implementation 'androidx.navigation:navigation-fragment:2.5.3'
|
implementation 'androidx.navigation:navigation-fragment:2.5.3'
|
||||||
implementation 'androidx.navigation:navigation-ui:2.5.3'
|
implementation 'androidx.navigation:navigation-ui:2.5.3'
|
||||||
implementation 'androidx.core:core-ktx:1.9.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
|
implementation 'androidx.core:core-ktx:+'
|
||||||
testImplementation "junit:junit:$junitVer"
|
testImplementation "junit:junit:$junitVer"
|
||||||
androidTestImplementation "androidx.test.ext:junit:$androidJunitVer"
|
androidTestImplementation "androidx.test.ext:junit:$androidJunitVer"
|
||||||
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVer"
|
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVer"
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "94d37ae85390ef5198651df2480a02bf",
|
"identityHash": "2c0fdec170ca54d97ef928dfe28a6992",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "results",
|
"tableName": "results",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL)",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `creationTime` INTEGER NOT NULL)",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "id",
|
||||||
|
|
@ -55,6 +55,12 @@
|
||||||
"columnName": "playlistTitle",
|
"columnName": "playlistTitle",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "creationTime",
|
||||||
|
"columnName": "creationTime",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
|
|
@ -386,7 +392,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '94d37ae85390ef5198651df2480a02bf')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2c0fdec170ca54d97ef928dfe28a6992')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,6 @@ abstract class DBManager : RoomDatabase(){
|
||||||
DBManager::class.java,
|
DBManager::class.java,
|
||||||
"YTDLnisDatabase"
|
"YTDLnisDatabase"
|
||||||
)
|
)
|
||||||
.allowMainThreadQueries()
|
|
||||||
.build()
|
.build()
|
||||||
instance = dbInstance
|
instance = dbInstance
|
||||||
dbInstance
|
dbInstance
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ interface DownloadDao {
|
||||||
fun getDownloadByWorkId(workID: Int) : DownloadItem
|
fun getDownloadByWorkId(workID: Int) : DownloadItem
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
||||||
fun getDownloadById(id: Int) : DownloadItem
|
fun getDownloadById(id: Long) : DownloadItem
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insert(item: DownloadItem) : Long
|
suspend fun insert(item: DownloadItem) : Long
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ data class DownloadItem(
|
||||||
var formatDesc: String,
|
var formatDesc: String,
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
val removeAudio: Boolean,
|
val removeAudio: Boolean,
|
||||||
val downloadPath: String,
|
var downloadPath: String,
|
||||||
val website: String,
|
val website: String,
|
||||||
val downloadSize: String,
|
val downloadSize: String,
|
||||||
val playlistTitle: String,
|
val playlistTitle: String,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.deniscerri.ytdlnis.database.models
|
||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Entity(tableName = "results")
|
@Entity(tableName = "results")
|
||||||
data class ResultItem(
|
data class ResultItem(
|
||||||
|
|
@ -13,5 +14,6 @@ data class ResultItem(
|
||||||
val duration: String,
|
val duration: String,
|
||||||
val thumb: String,
|
val thumb: String,
|
||||||
val website: String,
|
val website: String,
|
||||||
var playlistTitle: String
|
var playlistTitle: String,
|
||||||
|
var creationTime: Long = System.currentTimeMillis() / 1000,
|
||||||
)
|
)
|
||||||
|
|
@ -38,8 +38,8 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
update(item);
|
update(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLatest() : DownloadItem {
|
fun getItemByID(id: Long) : DownloadItem {
|
||||||
return downloadDao.getLatest()
|
return downloadDao.getDownloadById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
repository.update(item);
|
repository.update(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLatest() : DownloadItem {
|
fun getItemByID(id: Long) : DownloadItem {
|
||||||
return repository.getLatest()
|
return repository.getItemByID(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,15 +34,12 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
||||||
})
|
})
|
||||||
_items.addSource(formatFilter, Observer {
|
_items.addSource(formatFilter, Observer {
|
||||||
Log.e("aa", "audio");
|
|
||||||
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
||||||
})
|
})
|
||||||
_items.addSource(sortType, Observer {
|
_items.addSource(sortType, Observer {
|
||||||
Log.e("aa", "asssssssssssss");
|
|
||||||
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
||||||
})
|
})
|
||||||
_items.addSource(websiteFilter, Observer {
|
_items.addSource(websiteFilter, Observer {
|
||||||
Log.e("Aa", "website")
|
|
||||||
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
|
||||||
})
|
})
|
||||||
_items.addSource(queryFilter, Observer {
|
_items.addSource(queryFilter, Observer {
|
||||||
|
|
@ -56,7 +53,6 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSorting(sort: HistorySort){
|
fun setSorting(sort: HistorySort){
|
||||||
Log.e("aa", "asssssssssssss");
|
|
||||||
sortType.value = sort
|
sortType.value = sort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,7 +65,6 @@ class HistoryViewModel(application: Application) : AndroidViewModel(application)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFormatFilter(filter: String){
|
fun setFormatFilter(filter: String){
|
||||||
Log.e("aa", "audio");
|
|
||||||
formatFilter.value = filter
|
formatFilter.value = filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,12 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
|
fun checkTrending() = viewModelScope.launch(Dispatchers.IO){
|
||||||
try {
|
try {
|
||||||
val item = repository.getFirstResult()
|
val item = repository.getFirstResult()
|
||||||
if (item.playlistTitle == "ytdlnis-TRENDING") getTrending()
|
if (
|
||||||
|
item.playlistTitle == getApplication<App>().getString(R.string.trendingPlaylist)
|
||||||
|
&& item.creationTime < (System.currentTimeMillis() / 1000) - 86400
|
||||||
|
){
|
||||||
|
getTrending()
|
||||||
|
}
|
||||||
}catch (e : Exception){
|
}catch (e : Exception){
|
||||||
getTrending()
|
getTrending()
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +63,6 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
} else if (inputQuery!!.contains("http")) {
|
} else if (inputQuery!!.contains("http")) {
|
||||||
type = "Default"
|
type = "Default"
|
||||||
}
|
}
|
||||||
Log.e(tag, "$inputQuery $type")
|
|
||||||
try {
|
try {
|
||||||
when (type) {
|
when (type) {
|
||||||
"Search" -> {
|
"Search" -> {
|
||||||
|
|
@ -102,12 +106,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
|
|
||||||
when(type){
|
when(type){
|
||||||
"audio" -> {
|
"audio" -> {
|
||||||
list = list.filter { it.format_note.contains("audio", ignoreCase = true) }
|
return list.filter { it.format_note.contains("audio", ignoreCase = true) }
|
||||||
if (list.isEmpty()) {
|
|
||||||
audioFormats.forEach { formats.add(Format(0, item.id, it, "", 0, it, "")) }
|
|
||||||
return formats
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
"video" -> {
|
"video" -> {
|
||||||
list = list.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
list = list.filter { !it.format_note.contains("audio", ignoreCase = true) }
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
import com.facebook.shimmer.ShimmerFrameLayout
|
import com.facebook.shimmer.ShimmerFrameLayout
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.ChipGroup
|
import com.google.android.material.chip.ChipGroup
|
||||||
|
|
@ -86,6 +87,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
private var selectedObjects: ArrayList<ResultItem>? = null
|
private var selectedObjects: ArrayList<ResultItem>? = null
|
||||||
private var deleteFab: ExtendedFloatingActionButton? = null
|
private var deleteFab: ExtendedFloatingActionButton? = null
|
||||||
private var fileUtil: FileUtil? = null
|
private var fileUtil: FileUtil? = null
|
||||||
|
private var firstBoot = true
|
||||||
|
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
|
|
||||||
|
|
@ -144,10 +146,15 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
homeAdapter!!.submitList(it)
|
homeAdapter!!.submitList(it)
|
||||||
resultsList = it
|
resultsList = it
|
||||||
if(it.size > 1){
|
if(it.size > 1){
|
||||||
if (it[0].playlistTitle.isNotEmpty() || it[0].playlistTitle != getString(R.string.trendingPlaylist)){
|
if (it[0].playlistTitle.isNotEmpty() && it[0].playlistTitle != getString(R.string.trendingPlaylist)){
|
||||||
downloadAllFabCoordinator!!.visibility = VISIBLE
|
downloadAllFabCoordinator!!.visibility = VISIBLE
|
||||||
|
}else{
|
||||||
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
}
|
}
|
||||||
|
}else if(it.size == 1 && !firstBoot && parentFragmentManager.findFragmentByTag("bottomSheet") == null){
|
||||||
|
showSingleDownloadSheet(it[0], "audio")
|
||||||
}
|
}
|
||||||
|
firstBoot = false
|
||||||
}
|
}
|
||||||
|
|
||||||
resultViewModel.loadingItems.observe(viewLifecycleOwner){
|
resultViewModel.loadingItems.observe(viewLifecycleOwner){
|
||||||
|
|
@ -349,9 +356,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// selectedObjects!!.clear()
|
// selectedObjects!!.clear()
|
||||||
// selectedObjects!!.add(item!!)
|
// selectedObjects!!.add(item!!)
|
||||||
//showConfigureSingleDownloadCard(createDownloadItem(item!!, type), item)
|
//showConfigureSingleDownloadCard(createDownloadItem(item!!, type), item)
|
||||||
createDownloadItem(item!!, type){
|
showSingleDownloadSheet(item!!, type)
|
||||||
showSingleDownloadSheet(it)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// downloadQueue!!.add(vid)
|
// downloadQueue!!.add(vid)
|
||||||
// updateDownloadingStatusOnResult(vid, type, true)
|
// updateDownloadingStatusOnResult(vid, type, true)
|
||||||
|
|
@ -362,12 +367,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSingleDownloadSheet(item : DownloadItem){
|
private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){
|
||||||
val bottomSheet = DownloadBottomSheetDialog(item)
|
|
||||||
bottomSheet.show(parentFragmentManager, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createDownloadItem(item: ResultItem, type: String, itemCreated: (DownloadItem) -> Unit) : DownloadItem {
|
|
||||||
val sharedPreferences =
|
val sharedPreferences =
|
||||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
||||||
|
|
@ -376,22 +376,22 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
|
|
||||||
|
|
||||||
val downloadItem = DownloadItem(0,
|
val downloadItem = DownloadItem(0,
|
||||||
item.url,
|
resultItem.url,
|
||||||
item.title,
|
resultItem.title,
|
||||||
item.author,
|
resultItem.author,
|
||||||
item.thumb,
|
resultItem.thumb,
|
||||||
item.duration,
|
resultItem.duration,
|
||||||
type,
|
type,
|
||||||
"", "", 0, "", false,
|
"", "", 0, "", false,
|
||||||
"", item.website, "", item.playlistTitle, embedSubs, addChapters, saveThumb, "",
|
"", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, "",
|
||||||
"", DownloadRepository.status.Processing.toString(), 0
|
"", DownloadRepository.status.Processing.toString(), 0
|
||||||
)
|
)
|
||||||
|
|
||||||
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) {
|
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) {
|
||||||
downloadItem.id = it
|
downloadItem.id = it
|
||||||
itemCreated(downloadItem)
|
val bottomSheet = DownloadBottomSheetDialog(downloadItem)
|
||||||
|
bottomSheet.show(parentFragmentManager, "bottomSheet")
|
||||||
}
|
}
|
||||||
return downloadItem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.deniscerri.ytdlnis.ui.downloadcard
|
package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
|
@ -8,33 +9,56 @@ import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.widget.*
|
||||||
import android.widget.AdapterView
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.AutoCompleteTextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
||||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class DownloadAudioFragment(item: DownloadItem) : Fragment() {
|
class DownloadAudioFragment(private val downloadItem: DownloadItem) : Fragment() {
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
private var mainActivity: MainActivity? = null
|
private var mainActivity: MainActivity? = null
|
||||||
private lateinit var resultViewModel : ResultViewModel
|
private lateinit var resultViewModel : ResultViewModel
|
||||||
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
private lateinit var fileUtil : FileUtil
|
private lateinit var fileUtil : FileUtil
|
||||||
private val downloadItem = item
|
|
||||||
|
|
||||||
|
private lateinit var title : TextInputLayout
|
||||||
|
private lateinit var author : TextInputLayout
|
||||||
|
private lateinit var saveDir : TextInputLayout
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
lifecycleScope.launch{
|
||||||
|
val item = withContext(Dispatchers.IO){
|
||||||
|
downloadViewModel.getItemByID(downloadItem.id)
|
||||||
|
}
|
||||||
|
if (::title.isInitialized){
|
||||||
|
title.editText!!.setText(item.title)
|
||||||
|
downloadItem.title = item.title
|
||||||
|
}
|
||||||
|
if(::author.isInitialized){
|
||||||
|
author.editText!!.setText(item.author)
|
||||||
|
downloadItem.author = item.author
|
||||||
|
}
|
||||||
|
}
|
||||||
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
|
@ -46,109 +70,176 @@ class DownloadAudioFragment(item: DownloadItem) : Fragment() {
|
||||||
activity = getActivity()
|
activity = getActivity()
|
||||||
mainActivity = activity as MainActivity?
|
mainActivity = activity as MainActivity?
|
||||||
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
resultViewModel = ViewModelProvider(this)[ResultViewModel::class.java]
|
||||||
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
fileUtil = FileUtil()
|
fileUtil = FileUtil()
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val resultItem = withContext(Dispatchers.IO){
|
||||||
|
resultViewModel.getItemByURL(downloadItem.url)
|
||||||
|
}
|
||||||
|
val type = downloadItem.type
|
||||||
|
|
||||||
val resultItem = resultViewModel.getItemByURL(downloadItem.url)
|
val sharedPreferences =
|
||||||
val type = downloadItem.type
|
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
|
|
||||||
val sharedPreferences =
|
try {
|
||||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
title = view.findViewById(R.id.title_textinput)
|
||||||
|
title.editText!!.setText(downloadItem.title)
|
||||||
|
title.editText!!.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
|
downloadItem.title = p0.toString()
|
||||||
|
resultItem.title = p0.toString()
|
||||||
|
resultViewModel.update(resultItem)
|
||||||
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
try {
|
author = view.findViewById(R.id.author_textinput)
|
||||||
val title = view.findViewById<TextInputLayout>(R.id.title_textinput)
|
author.editText!!.setText(downloadItem.author)
|
||||||
title!!.editText!!.setText(downloadItem.title)
|
author.editText!!.addTextChangedListener(object : TextWatcher {
|
||||||
title.editText!!.addTextChangedListener(object : TextWatcher {
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
override fun afterTextChanged(p0: Editable?) {
|
downloadItem.author = p0.toString()
|
||||||
downloadItem.title = p0.toString()
|
resultItem.author = p0.toString()
|
||||||
resultItem.title = p0.toString()
|
resultViewModel.update(resultItem)
|
||||||
resultViewModel.update(resultItem)
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
saveDir = view.findViewById(R.id.outputPath)
|
||||||
val author = view.findViewById<TextInputLayout>(R.id.author_textinput)
|
val downloadPath = sharedPreferences.getString(
|
||||||
author!!.editText!!.setText(downloadItem.author)
|
|
||||||
author.editText!!.addTextChangedListener(object : TextWatcher {
|
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
|
||||||
override fun afterTextChanged(p0: Editable?) {
|
|
||||||
downloadItem.author = p0.toString()
|
|
||||||
resultItem.author = p0.toString()
|
|
||||||
resultViewModel.update(resultItem)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
val saveDir = view.findViewById<TextInputLayout>(R.id.outputPath)
|
|
||||||
saveDir!!.editText!!.setText(
|
|
||||||
sharedPreferences.getString(
|
|
||||||
"music_path",
|
"music_path",
|
||||||
getString(R.string.music_path)
|
getString(R.string.music_path)
|
||||||
)
|
)
|
||||||
)
|
downloadItem.downloadPath = downloadPath!!
|
||||||
saveDir.editText!!.isFocusable = false;
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
saveDir.editText!!.isClickable = true;
|
saveDir.editText!!.setText(
|
||||||
saveDir.editText!!.setOnClickListener {
|
fileUtil.formatPath(downloadPath)
|
||||||
Toast.makeText(context, "TEST", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
val formats = resultViewModel.getFormats(resultItem, type)
|
|
||||||
|
|
||||||
val formatTitles = formats.map {
|
|
||||||
if (it.format_note.contains("AUDIO_QUALITY_"))
|
|
||||||
it.format_note.replace("AUDIO_QUALITY_", "") +
|
|
||||||
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
|
||||||
else it.format_note +
|
|
||||||
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
|
||||||
}
|
|
||||||
|
|
||||||
val format = view.findViewById<TextInputLayout>(R.id.format)
|
|
||||||
val autoCompleteTextView =
|
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.format_textview)
|
|
||||||
autoCompleteTextView?.setAdapter(
|
|
||||||
ArrayAdapter(
|
|
||||||
requireContext(),
|
|
||||||
android.R.layout.simple_dropdown_item_1line,
|
|
||||||
formatTitles
|
|
||||||
)
|
)
|
||||||
)
|
saveDir.editText!!.isFocusable = false;
|
||||||
if (formatTitles.isNotEmpty()){
|
saveDir.editText!!.isClickable = true;
|
||||||
autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
|
saveDir.editText!!.setOnClickListener {
|
||||||
}
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
(format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
downloadItem.formatDesc = formats[index].format_note
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||||
downloadItem.audioFormatId = formats[index].format_id
|
audioPathResultLauncher.launch(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
val containers = requireContext().resources.getStringArray(R.array.audio_containers)
|
val formats = withContext(Dispatchers.IO){
|
||||||
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
resultViewModel.getFormats(resultItem, type)
|
||||||
val containerAutoCompleteTextView =
|
}
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
val format = view.findViewById<TextInputLayout>(R.id.format)
|
||||||
|
if (formats.isEmpty()) {
|
||||||
|
format.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
val formatTitles = formats.map {
|
||||||
|
if (it.format_note.contains("AUDIO_QUALITY_")) {
|
||||||
|
it.format_note.replace(
|
||||||
|
"AUDIO_QUALITY_",
|
||||||
|
""
|
||||||
|
) + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
||||||
|
} else {
|
||||||
|
it.format_note + if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(
|
||||||
|
it.filesize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
container?.isEnabled = true
|
val autoCompleteTextView =
|
||||||
containerAutoCompleteTextView?.setAdapter(
|
view.findViewById<AutoCompleteTextView>(R.id.format_textview)
|
||||||
ArrayAdapter(
|
autoCompleteTextView?.setAdapter(
|
||||||
requireContext(),
|
ArrayAdapter(
|
||||||
android.R.layout.simple_dropdown_item_1line,
|
requireContext(),
|
||||||
containers
|
android.R.layout.simple_dropdown_item_1line,
|
||||||
)
|
formatTitles
|
||||||
)
|
)
|
||||||
val selectedContainer: String = formats.find { downloadItem.formatDesc == it.format_note }?.container
|
)
|
||||||
?: sharedPreferences.getString("audio_format", "mp3")!!
|
if (formatTitles.isNotEmpty()) {
|
||||||
containerAutoCompleteTextView!!.setText(selectedContainer, false)
|
autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
|
||||||
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
}
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
(format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
downloadItem.ext = containers[index]
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
downloadItem.formatDesc = formats[index].format_note
|
||||||
|
downloadItem.audioFormatId = formats[index].format_id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (e : Exception){
|
val containers = requireContext().resources.getStringArray(R.array.audio_containers)
|
||||||
e.printStackTrace()
|
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
||||||
|
val containerAutoCompleteTextView =
|
||||||
|
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
||||||
|
|
||||||
|
container?.isEnabled = true
|
||||||
|
containerAutoCompleteTextView?.setAdapter(
|
||||||
|
ArrayAdapter(
|
||||||
|
requireContext(),
|
||||||
|
android.R.layout.simple_dropdown_item_1line,
|
||||||
|
containers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val selectedContainer: String = formats.find { downloadItem.formatDesc == it.format_note }?.container
|
||||||
|
?: sharedPreferences.getString("audio_format", "mp3")!!
|
||||||
|
containerAutoCompleteTextView!!.setText(selectedContainer, false)
|
||||||
|
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
downloadItem.ext = containers[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val cancelBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_cancel_button)
|
||||||
|
cancelBtn.setOnClickListener{
|
||||||
|
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
|
||||||
|
}
|
||||||
|
|
||||||
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
|
download!!.setOnClickListener {
|
||||||
|
// for (i in selectedObjects!!.indices) {
|
||||||
|
// val vid = findVideo(
|
||||||
|
// selectedObjects!![i]!!.getURL()
|
||||||
|
// )
|
||||||
|
// vid!!.downloadedType = type
|
||||||
|
// updateDownloadingStatusOnResult(vid, type, true)
|
||||||
|
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
||||||
|
// downloadQueue!!.add(vid)
|
||||||
|
// }
|
||||||
|
// selectedObjects = ArrayList()
|
||||||
|
// homeAdapter!!.clearCheckedVideos()
|
||||||
|
// downloadFabs!!.visibility = View.GONE
|
||||||
|
// if (isStoragePermissionGranted) {
|
||||||
|
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
||||||
|
// downloadQueue!!.clear()
|
||||||
|
// }
|
||||||
|
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch (e : Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var audioPathResultLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
result.data?.data?.let {
|
||||||
|
activity?.contentResolver?.takePersistableUriPermission(
|
||||||
|
it,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
downloadItem.downloadPath = result.data?.data.toString()
|
||||||
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
|
saveDir.editText?.setText(fileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,17 +4,15 @@ import android.annotation.SuppressLint
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import androidx.fragment.app.FragmentTransaction
|
||||||
import android.widget.Toast
|
import androidx.fragment.app.findFragment
|
||||||
import androidx.core.view.get
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
|
||||||
|
|
@ -42,6 +40,7 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
|
||||||
val fragmentManager = parentFragmentManager
|
val fragmentManager = parentFragmentManager
|
||||||
fragmentAdapter = DownloadFragmentAdapter(downloadItem, fragmentManager, lifecycle)
|
fragmentAdapter = DownloadFragmentAdapter(downloadItem, fragmentManager, lifecycle)
|
||||||
viewPager2.adapter = fragmentAdapter
|
viewPager2.adapter = fragmentAdapter
|
||||||
|
viewPager2.isSaveFromParentEnabled = false
|
||||||
|
|
||||||
when(downloadItem.type) {
|
when(downloadItem.type) {
|
||||||
"audio" -> {
|
"audio" -> {
|
||||||
|
|
@ -80,6 +79,12 @@ class DownloadBottomSheetDialog(item: DownloadItem) : BottomSheetDialogFragment(
|
||||||
|
|
||||||
override fun onCancel(dialog: DialogInterface) {
|
override fun onCancel(dialog: DialogInterface) {
|
||||||
super.onCancel(dialog)
|
super.onCancel(dialog)
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("bottomSheet")!!).commit()
|
||||||
|
for (i in 0 until viewPager2.adapter?.itemCount!!){
|
||||||
|
if (parentFragmentManager.findFragmentByTag("f${i}") != null){
|
||||||
|
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("f$i")!!).commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
downloadViewModel.deleteDownload(downloadItem)
|
downloadViewModel.deleteDownload(downloadItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package com.deniscerri.ytdlnis.ui.downloadcard
|
package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
class DownloadFragmentAdapter (item : DownloadItem, fragmentManager : FragmentManager, lifecycle : Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) {
|
class DownloadFragmentAdapter (item : DownloadItem, fragmentManager : FragmentManager, lifecycle : Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) {
|
||||||
private val downloadItem = item
|
private val downloadItem = item
|
||||||
|
|
@ -18,14 +20,19 @@ class DownloadFragmentAdapter (item : DownloadItem, fragmentManager : FragmentMa
|
||||||
when (position) {
|
when (position) {
|
||||||
0 -> {
|
0 -> {
|
||||||
downloadItem.type = "audio"
|
downloadItem.type = "audio"
|
||||||
return DownloadAudioFragment(downloadItem)
|
return DownloadAudioFragment(clone(downloadItem))
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
downloadItem.type = "video"
|
downloadItem.type = "video"
|
||||||
return DownloadVideoFragment(downloadItem)
|
return DownloadVideoFragment(clone(downloadItem))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
downloadItem.type = "command"
|
downloadItem.type = "command"
|
||||||
return DownloadCommandFragment(downloadItem)
|
return DownloadCommandFragment(clone(downloadItem))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clone(item: DownloadItem) : DownloadItem {
|
||||||
|
val stringItem = Gson().toJson(item, DownloadItem::class.java)
|
||||||
|
return Gson().fromJson(stringItem, DownloadItem::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.deniscerri.ytdlnis.ui.downloadcard
|
package com.deniscerri.ytdlnis.ui.downloadcard
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
|
@ -8,8 +9,10 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
|
@ -17,10 +20,14 @@ import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class DownloadVideoFragment(item: DownloadItem) : Fragment() {
|
class DownloadVideoFragment(private val downloadItem: DownloadItem) : Fragment() {
|
||||||
private var _binding : FragmentHomeBinding? = null
|
private var _binding : FragmentHomeBinding? = null
|
||||||
private var fragmentView: View? = null
|
private var fragmentView: View? = null
|
||||||
private var activity: Activity? = null
|
private var activity: Activity? = null
|
||||||
|
|
@ -28,8 +35,28 @@ class DownloadVideoFragment(item: DownloadItem) : Fragment() {
|
||||||
private lateinit var resultViewModel : ResultViewModel
|
private lateinit var resultViewModel : ResultViewModel
|
||||||
private lateinit var downloadViewModel : DownloadViewModel
|
private lateinit var downloadViewModel : DownloadViewModel
|
||||||
private lateinit var fileUtil : FileUtil
|
private lateinit var fileUtil : FileUtil
|
||||||
private val downloadItem = item
|
|
||||||
|
|
||||||
|
private lateinit var title : TextInputLayout
|
||||||
|
private lateinit var author : TextInputLayout
|
||||||
|
private lateinit var saveDir : TextInputLayout
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
lifecycleScope.launch{
|
||||||
|
val item = withContext(Dispatchers.IO){
|
||||||
|
downloadViewModel.getItemByID(downloadItem.id)
|
||||||
|
}
|
||||||
|
if (::title.isInitialized){
|
||||||
|
title.editText!!.setText(item.title)
|
||||||
|
downloadItem.title = item.title
|
||||||
|
}
|
||||||
|
if(::author.isInitialized){
|
||||||
|
author.editText!!.setText(item.author)
|
||||||
|
downloadItem.author = item.author
|
||||||
|
}
|
||||||
|
}
|
||||||
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
|
}
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
|
@ -45,122 +72,135 @@ class DownloadVideoFragment(item: DownloadItem) : Fragment() {
|
||||||
return fragmentView
|
return fragmentView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
val resultItem = resultViewModel.getItemByURL(downloadItem.url)
|
lifecycleScope.launch {
|
||||||
val type = downloadItem.type
|
val resultItem = withContext(Dispatchers.IO){
|
||||||
|
resultViewModel.getItemByURL(downloadItem.url)
|
||||||
|
}
|
||||||
|
val type = downloadItem.type
|
||||||
|
|
||||||
val sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
val sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val title = view.findViewById<TextInputLayout>(R.id.title_textinput)
|
title = view.findViewById(R.id.title_textinput)
|
||||||
title!!.editText!!.setText(downloadItem.title)
|
title.editText!!.setText(downloadItem.title)
|
||||||
title.editText!!.addTextChangedListener(object : TextWatcher {
|
title.editText!!.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun afterTextChanged(p0: Editable?) {
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
downloadItem.title = p0.toString()
|
downloadItem.title = p0.toString()
|
||||||
resultItem.title = p0.toString()
|
resultItem.title = p0.toString()
|
||||||
resultViewModel.update(resultItem)
|
resultViewModel.update(resultItem)
|
||||||
downloadViewModel.updateDownload(downloadItem)
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
val author = view.findViewById<TextInputLayout>(R.id.author_textinput)
|
author = view.findViewById(R.id.author_textinput)
|
||||||
author!!.editText!!.setText(downloadItem.author)
|
author.editText!!.setText(downloadItem.author)
|
||||||
author.editText!!.addTextChangedListener(object : TextWatcher {
|
author.editText!!.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
override fun afterTextChanged(p0: Editable?) {
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
downloadItem.author = p0.toString()
|
downloadItem.author = p0.toString()
|
||||||
resultItem.author = p0.toString()
|
resultItem.author = p0.toString()
|
||||||
resultViewModel.update(resultItem)
|
resultViewModel.update(resultItem)
|
||||||
downloadViewModel.updateDownload(downloadItem)
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
val saveDir = view.findViewById<TextInputLayout>(R.id.outputPath)
|
saveDir = view.findViewById(R.id.outputPath)
|
||||||
saveDir!!.editText!!.setText(
|
val downloadPath = sharedPreferences.getString(
|
||||||
sharedPreferences.getString(
|
|
||||||
"video_path",
|
"video_path",
|
||||||
getString(R.string.video_path)
|
getString(R.string.video_path)
|
||||||
)
|
)
|
||||||
)
|
downloadItem.downloadPath = downloadPath!!
|
||||||
saveDir.editText!!.isFocusable = false;
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
saveDir.editText!!.isClickable = true;
|
saveDir.editText!!.setText(
|
||||||
saveDir.editText!!.setOnClickListener {
|
fileUtil.formatPath(downloadPath)
|
||||||
Toast.makeText(context, "TEST", Toast.LENGTH_SHORT).show()
|
)
|
||||||
}
|
saveDir.editText!!.isFocusable = false;
|
||||||
|
saveDir.editText!!.isClickable = true;
|
||||||
|
saveDir.editText!!.setOnClickListener {
|
||||||
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
||||||
|
videoPathResultLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
|
||||||
val formats = resultViewModel.getFormats(resultItem, type)
|
val formats = withContext(Dispatchers.IO){
|
||||||
|
resultViewModel.getFormats(resultItem, type)
|
||||||
|
}
|
||||||
|
|
||||||
val formatTitles = formats.map {
|
val formatTitles = formats.map {
|
||||||
if (it.format_note.contains("AUDIO_QUALITY_"))
|
if (it.format_note.contains("AUDIO_QUALITY_"))
|
||||||
it.format_note.replace("AUDIO_QUALITY_", "") +
|
it.format_note.replace("AUDIO_QUALITY_", "") +
|
||||||
|
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
||||||
|
else it.format_note +
|
||||||
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
||||||
else it.format_note +
|
|
||||||
if (it.filesize == 0L) "" else " / " + fileUtil.convertFileSize(it.filesize)
|
|
||||||
}
|
|
||||||
|
|
||||||
val format = view.findViewById<TextInputLayout>(R.id.format)
|
|
||||||
val autoCompleteTextView =
|
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.format_textview)
|
|
||||||
autoCompleteTextView?.setAdapter(
|
|
||||||
ArrayAdapter(
|
|
||||||
requireContext(),
|
|
||||||
android.R.layout.simple_dropdown_item_1line,
|
|
||||||
formatTitles
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (formatTitles.isNotEmpty()) {
|
|
||||||
autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
|
|
||||||
}
|
|
||||||
(format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
|
||||||
downloadItem.formatDesc = formats[index].format_note
|
|
||||||
downloadItem.videoFormatId = formats[index].format_id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val containers = requireContext().resources.getStringArray(R.array.video_containers)
|
val format = view.findViewById<TextInputLayout>(R.id.format)
|
||||||
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
val autoCompleteTextView =
|
||||||
val containerAutoCompleteTextView =
|
view.findViewById<AutoCompleteTextView>(R.id.format_textview)
|
||||||
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
autoCompleteTextView?.setAdapter(
|
||||||
|
ArrayAdapter(
|
||||||
container?.isEnabled = true
|
requireContext(),
|
||||||
containerAutoCompleteTextView?.setAdapter(
|
android.R.layout.simple_dropdown_item_1line,
|
||||||
ArrayAdapter(
|
formatTitles
|
||||||
requireContext(),
|
)
|
||||||
android.R.layout.simple_dropdown_item_1line,
|
|
||||||
containers
|
|
||||||
)
|
)
|
||||||
)
|
if (formatTitles.isNotEmpty()) {
|
||||||
val selectedContainer: String =
|
autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
|
||||||
formats.find { downloadItem.formatDesc == it.format_note }?.container
|
|
||||||
?: sharedPreferences.getString("video_format", "DEFAULT")!!
|
|
||||||
containerAutoCompleteTextView!!.setText(selectedContainer, false)
|
|
||||||
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
|
||||||
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
|
||||||
downloadItem.ext = containers[index]
|
|
||||||
}
|
}
|
||||||
|
(format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
downloadItem.formatDesc = formats[index].format_note
|
||||||
|
downloadItem.videoFormatId = formats[index].format_id
|
||||||
|
}
|
||||||
|
|
||||||
val embedSubs = view.findViewById<Chip>(R.id.embed_subtitles)
|
val containers = requireContext().resources.getStringArray(R.array.video_containers)
|
||||||
|
val container = view.findViewById<TextInputLayout>(R.id.downloadContainer)
|
||||||
|
val containerAutoCompleteTextView =
|
||||||
|
view.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
||||||
|
|
||||||
|
container?.isEnabled = true
|
||||||
|
containerAutoCompleteTextView?.setAdapter(
|
||||||
|
ArrayAdapter(
|
||||||
|
requireContext(),
|
||||||
|
android.R.layout.simple_dropdown_item_1line,
|
||||||
|
containers
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val selectedContainer: String =
|
||||||
|
formats.find { downloadItem.formatDesc == it.format_note }?.container
|
||||||
|
?: sharedPreferences.getString("video_format", "DEFAULT")!!
|
||||||
|
containerAutoCompleteTextView!!.setText(selectedContainer, false)
|
||||||
|
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
downloadItem.ext = containers[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
val embedSubs = view.findViewById<Chip>(R.id.embed_subtitles)
|
||||||
embedSubs!!.isChecked = sharedPreferences.getBoolean("embed_subtitles", false)
|
embedSubs!!.isChecked = sharedPreferences.getBoolean("embed_subtitles", false)
|
||||||
|
|
||||||
val addChapters = view.findViewById<Chip>(R.id.add_chapters)
|
val addChapters = view.findViewById<Chip>(R.id.add_chapters)
|
||||||
addChapters!!.isChecked = sharedPreferences.getBoolean("add_chapters", false)
|
addChapters!!.isChecked = sharedPreferences.getBoolean("add_chapters", false)
|
||||||
|
|
||||||
val saveThumbnail = view.findViewById<Chip>(R.id.save_thumbnail)
|
val saveThumbnail = view.findViewById<Chip>(R.id.save_thumbnail)
|
||||||
saveThumbnail!!.isChecked = sharedPreferences.getBoolean("write_thumbnail", false)
|
saveThumbnail!!.isChecked = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||||
|
|
||||||
|
|
||||||
val cancel = view.findViewById<Button>(R.id.bottomsheet_cancel_button)
|
val cancel = view.findViewById<Button>(R.id.bottomsheet_cancel_button)
|
||||||
cancel!!.setOnClickListener {
|
cancel!!.setOnClickListener {
|
||||||
parentFragmentManager.popBackStack()
|
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
|
||||||
}
|
}
|
||||||
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
|
||||||
download!!.setOnClickListener {
|
download!!.setOnClickListener {
|
||||||
// for (i in selectedObjects!!.indices) {
|
// for (i in selectedObjects!!.indices) {
|
||||||
// val vid = findVideo(
|
// val vid = findVideo(
|
||||||
// selectedObjects!![i]!!.getURL()
|
// selectedObjects!![i]!!.getURL()
|
||||||
|
|
@ -177,11 +217,29 @@ class DownloadVideoFragment(item: DownloadItem) : Fragment() {
|
||||||
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
||||||
// downloadQueue!!.clear()
|
// downloadQueue!!.clear()
|
||||||
// }
|
// }
|
||||||
parentFragmentManager.popBackStack()
|
(parentFragmentManager.findFragmentByTag("bottomSheet") as DownloadBottomSheetDialog).dismissSelf()
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var videoPathResultLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.StartActivityForResult()
|
||||||
|
) { result ->
|
||||||
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
result.data?.data?.let {
|
||||||
|
activity?.contentResolver?.takePersistableUriPermission(
|
||||||
|
it,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
downloadItem.downloadPath = result.data?.data.toString()
|
||||||
|
downloadViewModel.updateDownload(downloadItem)
|
||||||
|
saveDir.editText?.setText(fileUtil.formatPath(result.data?.data.toString()), TextView.BufferType.EDITABLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -313,8 +313,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
private fun changePath(p: Preference?, data: Intent?, requestCode: Int) {
|
||||||
Log.e("TEST", data!!.toUri(0))
|
val path = data!!.data.toString()
|
||||||
val path = data.data.toString()
|
|
||||||
p!!.summary = fileUtil?.formatPath(data.data.toString())
|
p!!.summary = fileUtil?.formatPath(data.data.toString())
|
||||||
val sharedPreferences =
|
val sharedPreferences =
|
||||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ class FileUtil() {
|
||||||
|
|
||||||
fun formatPath(path: String) : String {
|
fun formatPath(path: String) : String {
|
||||||
var dataValue = path
|
var dataValue = path
|
||||||
|
if (dataValue.startsWith("/storage/")) return dataValue
|
||||||
dataValue = dataValue.replace("content://com.android.externalstorage.documents/tree/", "")
|
dataValue = dataValue.replace("content://com.android.externalstorage.documents/tree/", "")
|
||||||
dataValue = dataValue.replace("%3A".toRegex(), "/")
|
dataValue = dataValue.replace("%3A".toRegex(), "/")
|
||||||
try {
|
try {
|
||||||
|
|
@ -123,7 +124,7 @@ class FileUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertFileSize(s: Long): String{
|
fun convertFileSize(s: Long): String{
|
||||||
if (s <= 0) return "0"
|
if (s <= 0) return "?"
|
||||||
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||||
val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt()
|
val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt()
|
||||||
return DecimalFormat("#,##0.#").format(s / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
|
return DecimalFormat("#,##0.#").format(s / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
|
||||||
|
|
|
||||||
|
|
@ -474,11 +474,7 @@ class InfoUtil(context: Context) {
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
arrayOf(youtubeDLResponse.out)
|
arrayOf(youtubeDLResponse.out)
|
||||||
}
|
}
|
||||||
var isPlaylist = 0
|
|
||||||
val pl = JSONObject(results[0]!!)
|
val pl = JSONObject(results[0]!!)
|
||||||
if (pl.has("playlist")) {
|
|
||||||
if (pl.getString("playlist") != query) isPlaylist = 1
|
|
||||||
}
|
|
||||||
for (result in results) {
|
for (result in results) {
|
||||||
val jsonObject = JSONObject(result!!)
|
val jsonObject = JSONObject(result!!)
|
||||||
val title = if (jsonObject.has("title")) {
|
val title = if (jsonObject.has("title")) {
|
||||||
|
|
@ -506,6 +502,7 @@ class InfoUtil(context: Context) {
|
||||||
val website = if (jsonObject.has("ie_key")) jsonObject.getString("ie_key") else jsonObject.getString("extractor")
|
val website = if (jsonObject.has("ie_key")) jsonObject.getString("ie_key") else jsonObject.getString("extractor")
|
||||||
var playlistTitle: String? = ""
|
var playlistTitle: String? = ""
|
||||||
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
||||||
|
if(playlistTitle.equals(query)) playlistTitle = ""
|
||||||
val formatsInJSON = if (jsonObject.has("formats")) jsonObject.getJSONArray("formats") else null
|
val formatsInJSON = if (jsonObject.has("formats")) jsonObject.getJSONArray("formats") else null
|
||||||
val formats : ArrayList<Format> = ArrayList()
|
val formats : ArrayList<Format> = ArrayList()
|
||||||
if (formatsInJSON != null) {
|
if (formatsInJSON != null) {
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,8 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/bottom_sheet_title"
|
android:id="@+id/bottom_sheet_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:textSize="20sp"
|
android:textSize="25sp"
|
||||||
android:paddingTop="10dp"
|
android:padding="20dp"
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/download" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/bottom_sheet_subtitle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/configure_download" />
|
android:text="@string/configure_download" />
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:paddingBottom="10dp"
|
||||||
android:hint="@string/format">
|
android:hint="@string/audio_format">
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/format_textview"
|
android:id="@+id/format_textview"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
@ -78,7 +77,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:paddingBottom="10dp"
|
||||||
android:hint="@string/format">
|
android:hint="@string/video_format">
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/format_textview"
|
android:id="@+id/format_textview"
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:paddingBottom="10dp"
|
||||||
android:hint="@string/format">
|
android:hint="@string/video_format">
|
||||||
|
|
||||||
<AutoCompleteTextView
|
<AutoCompleteTextView
|
||||||
android:id="@+id/format_textview"
|
android:id="@+id/format_textview"
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/configure_download" />
|
android:text="@string/configure_download" />
|
||||||
|
|
||||||
<include layout="@layout/home_download_settings_components" />
|
|
||||||
|
|
||||||
<View style="@style/Divider.Horizontal"/>
|
<View style="@style/Divider.Horizontal"/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/title_textinput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/title"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/author_textinput"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="40"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/author"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/downloadContainer"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/container">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/container_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/audio_containers"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/format"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingBottom="20dp"
|
|
||||||
android:hint="@string/format">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/format_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/video_formats"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/outputPath"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/save_dir"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:id="@+id/downloadChipGroup"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:selectionRequired="true"
|
|
||||||
app:singleLine="true"
|
|
||||||
app:singleSelection="true">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/audioChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
android:text="@string/audio"
|
|
||||||
app:chipIcon="@drawable/ic_music" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/videoChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/video"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
app:chipIcon="@drawable/ic_video" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/commandChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/run_command"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
app:chipIcon="@drawable/ic_baseline_keyboard_arrow_right_24" />
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout android:id="@+id/history_element_bottom_sheet"
|
|
||||||
style="@style/Widget.Material3.BottomSheet"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/bottom_sheet_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:textSize="25sp"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/download" />
|
|
||||||
|
|
||||||
<include layout="@layout/home_download_settings_components" />
|
|
||||||
|
|
||||||
<View style="@style/Divider.Horizontal"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:id="@+id/bottomsheet_schedule_button"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:icon="@drawable/ic_clock"
|
|
||||||
android:text="@string/schedule" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:gravity="end"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:id="@+id/bottomsheet_cancel_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/cancel"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:icon="@drawable/ic_cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:id="@+id/bottomsheet_download_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/download"
|
|
||||||
app:icon="@drawable/ic_down"
|
|
||||||
android:autoLink="all"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
@ -65,9 +65,9 @@
|
||||||
<string name="choose_range_desc">Pick a range to download from the playlist (to not download everything).</string>
|
<string name="choose_range_desc">Pick a range to download from the playlist (to not download everything).</string>
|
||||||
<string name="last_cant_be_smaller_than_first">Last index cannot be smaller than the first.</string>
|
<string name="last_cant_be_smaller_than_first">Last index cannot be smaller than the first.</string>
|
||||||
<string name="first_cant_be_larger_than_last">First index cannot be larger than the last.</string>
|
<string name="first_cant_be_larger_than_last">First index cannot be larger than the last.</string>
|
||||||
<string name="music_path" translatable="false">/storage/emulated/0/Download/YTDLnis/Audio</string>
|
<string name="music_path" translatable="false">content://com.android.externalstorage.documents/tree/primary%3ADownload%2FYTDLnis%2FAudio</string>
|
||||||
<string name="video_path" translatable="false">/storage/emulated/0/Download/YTDLnis/Video</string>
|
<string name="video_path" translatable="false">content://com.android.externalstorage.documents/tree/primary%3ADownload%2FYTDLnis%2FVideo</string>
|
||||||
<string name="command_path" translatable="false">/storage/emulated/0/Download/YTDLnis/Command</string>
|
<string name="command_path" translatable="false">content://com.android.externalstorage.documents/tree/primary%3ADownload%2FYTDLnis%2FCommand</string>
|
||||||
<string name="concurrent_fragments_summary">Number of fragments of a DASH/HLS native video to download concurrently</string>
|
<string name="concurrent_fragments_summary">Number of fragments of a DASH/HLS native video to download concurrently</string>
|
||||||
<string name="concurrent_fragments">Concurrent Fragments</string>
|
<string name="concurrent_fragments">Concurrent Fragments</string>
|
||||||
<string name="downloading">Downloading</string>
|
<string name="downloading">Downloading</string>
|
||||||
|
|
@ -163,7 +163,6 @@
|
||||||
<string name="best">Best</string>
|
<string name="best">Best</string>
|
||||||
<string name="worst">Worst</string>
|
<string name="worst">Worst</string>
|
||||||
<string name="defaultValue">Default</string>
|
<string name="defaultValue">Default</string>
|
||||||
<string name="format">Format</string>
|
|
||||||
<string name="container">Container</string>
|
<string name="container">Container</string>
|
||||||
<string name="template">Template</string>
|
<string name="template">Template</string>
|
||||||
<string name="history">History</string>
|
<string name="history">History</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue