added select all to history & made chips in download card and active download card have same colors
This commit is contained in:
parent
0ae5d2c11f
commit
5b91db5834
13 changed files with 175 additions and 74 deletions
|
|
@ -137,7 +137,6 @@ dependencies {
|
|||
implementation "androidx.navigation:navigation-ui-ktx:$navVer"
|
||||
implementation "androidx.navigation:navigation-dynamic-features-fragment:$navVer"
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.test.ext:junit-ktx:1.1.5'
|
||||
implementation 'androidx.benchmark:benchmark-macro:1.1.1'
|
||||
testImplementation "junit:junit:$junitVer"
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".ui.more.TerminalActivity"
|
||||
android:configChanges="layoutDirection|locale"
|
||||
android:configChanges="layoutDirection|locale|orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:label="@string/terminal"
|
||||
android:parentActivityName=".MainActivity"
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ import androidx.lifecycle.lifecycleScope
|
|||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.CookieViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||
import com.deniscerri.ytdlnis.ui.HomeFragment
|
||||
import com.deniscerri.ytdlnis.ui.downloads.DownloadQueueActivity
|
||||
import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity
|
||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
|
@ -101,6 +103,17 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
cookieViewModel.updateCookiesFile()
|
||||
|
||||
//TODO PLAYLIST FORMAT UPDATING
|
||||
// val infoUtil = InfoUtil(context)
|
||||
// val list = arrayOf(
|
||||
// "https://www.youtube.com/watch?v=tYcqn48SMT8",
|
||||
// "https://www.youtube.com/watch?v=QNrNKPKe5oc"
|
||||
// )
|
||||
// infoUtil.getFormatsTest(list.toList()){
|
||||
// Log.e("gff", it.toString())
|
||||
// }
|
||||
|
||||
val intent = intent
|
||||
handleIntents(intent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import androidx.recyclerview.widget.ListAdapter
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
|
|
@ -170,6 +171,12 @@ class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activit
|
|||
checkedItems.clear()
|
||||
}
|
||||
|
||||
fun checkAll(items: List<HistoryItem?>?){
|
||||
checkedItems.clear()
|
||||
checkedItems.addAll(items!!.map { it!!.id })
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun invertSelected(items: List<HistoryItem?>?){
|
||||
val invertedList = mutableListOf<Long>()
|
||||
items?.forEach {
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
downloadViewModel.turnResultItemsToDownloadItems(resultsList!!)
|
||||
}
|
||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(resultsList!!, downloadList.toMutableList())
|
||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
||||
} else {
|
||||
downloadViewModel.queueDownloads(downloadList)
|
||||
|
|
@ -584,7 +584,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
actionMode?.finish()
|
||||
|
||||
if (sharedPreferences!!.getBoolean("download_card", true)) {
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList.toMutableList())
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(selectedObjects!!, downloadList.toMutableList())
|
||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
||||
} else {
|
||||
downloadViewModel.queueDownloads(downloadList)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.adapter.ConfigureMultipleDownloadsAdapter
|
||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.CommandTemplateViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||
|
|
@ -40,7 +41,7 @@ import kotlinx.coroutines.withContext
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadItem>) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener,
|
||||
class DownloadMultipleBottomSheetDialog(private var results: List<ResultItem?>, private var items: MutableList<DownloadItem>) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener,
|
||||
ConfigureDownloadBottomSheetDialog.OnDownloadItemUpdateListener {
|
||||
private lateinit var downloadViewModel: DownloadViewModel
|
||||
private lateinit var commandTemplateViewModel: CommandTemplateViewModel
|
||||
|
|
@ -131,82 +132,88 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
|||
}
|
||||
|
||||
bottomAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
|
||||
val itemId = m.itemId
|
||||
if (itemId == R.id.folder) {
|
||||
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)
|
||||
pathResultLauncher.launch(intent)
|
||||
} else if (itemId == R.id.preferred_download_type){
|
||||
lifecycleScope.launch{
|
||||
val bottomSheet = BottomSheetDialog(requireContext())
|
||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
bottomSheet.setContentView(R.layout.download_type_sheet)
|
||||
when (m.itemId) {
|
||||
R.id.folder -> {
|
||||
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)
|
||||
pathResultLauncher.launch(intent)
|
||||
}
|
||||
R.id.preferred_download_type -> {
|
||||
lifecycleScope.launch{
|
||||
val bottomSheet = BottomSheetDialog(requireContext())
|
||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
bottomSheet.setContentView(R.layout.download_type_sheet)
|
||||
|
||||
// BUTTON ----------------------------------
|
||||
val audio = bottomSheet.findViewById<TextView>(R.id.audio)
|
||||
val video = bottomSheet.findViewById<TextView>(R.id.video)
|
||||
val command = bottomSheet.findViewById<TextView>(R.id.command)
|
||||
// BUTTON ----------------------------------
|
||||
val audio = bottomSheet.findViewById<TextView>(R.id.audio)
|
||||
val video = bottomSheet.findViewById<TextView>(R.id.video)
|
||||
val command = bottomSheet.findViewById<TextView>(R.id.command)
|
||||
|
||||
|
||||
withContext(Dispatchers.IO){
|
||||
val nr = commandTemplateViewModel.getTotalNumber()
|
||||
if(nr == 0){
|
||||
command!!.visibility = View.GONE
|
||||
}else{
|
||||
command!!.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
audio!!.setOnClickListener {
|
||||
items = downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.audio).toMutableList()
|
||||
listAdapter.submitList(items.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_audio_file_24)
|
||||
bottomSheet.cancel()
|
||||
}
|
||||
|
||||
video!!.setOnClickListener {
|
||||
items = downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.video).toMutableList()
|
||||
listAdapter.submitList(items.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_video_file_24)
|
||||
bottomSheet.cancel()
|
||||
}
|
||||
|
||||
command!!.setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
items = withContext(Dispatchers.IO){
|
||||
downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.command).toMutableList()
|
||||
withContext(Dispatchers.IO){
|
||||
val nr = commandTemplateViewModel.getTotalNumber()
|
||||
if(nr == 0){
|
||||
command!!.visibility = View.GONE
|
||||
}else{
|
||||
command!!.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
audio!!.setOnClickListener {
|
||||
items = downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.audio).toMutableList()
|
||||
listAdapter.submitList(items.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_insert_drive_file_24)
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_audio_file_24)
|
||||
bottomSheet.cancel()
|
||||
}
|
||||
|
||||
video!!.setOnClickListener {
|
||||
items = downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.video).toMutableList()
|
||||
listAdapter.submitList(items.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_video_file_24)
|
||||
bottomSheet.cancel()
|
||||
}
|
||||
|
||||
command!!.setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
items = withContext(Dispatchers.IO){
|
||||
downloadViewModel.switchDownloadType(items, DownloadViewModel.Type.command).toMutableList()
|
||||
}
|
||||
listAdapter.submitList(items.toList())
|
||||
listAdapter.notifyDataSetChanged()
|
||||
preferredDownloadType.setIcon(R.drawable.baseline_insert_drive_file_24)
|
||||
bottomSheet.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
bottomSheet.show()
|
||||
bottomSheet.window!!.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
|
||||
bottomSheet.show()
|
||||
bottomSheet.window!!.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
R.id.format -> {
|
||||
if (results.first()!!.formats.isEmpty()){
|
||||
|
||||
} else if (itemId == R.id.format){
|
||||
// val formatListCollection = items.map { it.format }
|
||||
// val commonFormats = getCommonFormats(formatListCollection)
|
||||
//
|
||||
// val listener = object : OnFormatClickListener {
|
||||
// override fun onFormatClick(allFormats: List<Format>, item: Format) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
||||
// val bottomSheet = FormatSelectionBottomSheetDialog(null, commonFormats.toList(), listener)
|
||||
// bottomSheet.show(parentFragmentManager, "formatSheet")
|
||||
// }
|
||||
}
|
||||
// val formatListCollection = items.map { it.format }
|
||||
// val commonFormats = getCommonFormats(formatListCollection)
|
||||
//
|
||||
// val listener = object : OnFormatClickListener {
|
||||
// override fun onFormatClick(allFormats: List<Format>, item: Format) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// if (parentFragmentManager.findFragmentByTag("formatSheet") == null){
|
||||
// val bottomSheet = FormatSelectionBottomSheetDialog(null, commonFormats.toList(), listener)
|
||||
// bottomSheet.show(parentFragmentManager, "formatSheet")
|
||||
// }
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ class SelectPlaylistItemsBottomSheetDialog(private val items: List<ResultItem?>,
|
|||
downloadItems.add(i)
|
||||
}
|
||||
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadItems)
|
||||
val bottomSheet = DownloadMultipleBottomSheetDialog(items, downloadItems)
|
||||
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -559,6 +559,13 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
|
|||
actionMode?.finish()
|
||||
true
|
||||
}
|
||||
R.id.select_all -> {
|
||||
historyAdapter?.checkAll(historyList)
|
||||
selectedObjects?.clear()
|
||||
historyList?.forEach { selectedObjects?.add(it!!) }
|
||||
mode?.title = getString(R.string.all_items_selected)
|
||||
true
|
||||
}
|
||||
R.id.invert_selected -> {
|
||||
historyAdapter?.invertSelected(historyList)
|
||||
val invertedList = arrayListOf<HistoryItem>()
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ import com.deniscerri.ytdlnis.R
|
|||
import com.deniscerri.ytdlnis.database.models.Format
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.yausername.youtubedl_android.YoutubeDL
|
||||
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
|
@ -22,6 +25,7 @@ import java.net.HttpURLConnection
|
|||
import java.net.URL
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class InfoUtil(private val context: Context) {
|
||||
private var items: ArrayList<ResultItem?>
|
||||
|
|
@ -498,6 +502,56 @@ class InfoUtil(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun getFormatsTest(urls: List<String>, progress: (progress: List<Format>) -> Unit){
|
||||
init()
|
||||
val urlsFile = File(context.cacheDir, "urls.txt")
|
||||
urlsFile.delete()
|
||||
urlsFile.createNewFile()
|
||||
urls.forEach {
|
||||
urlsFile.appendText(it+"\n")
|
||||
}
|
||||
try {
|
||||
val request = YoutubeDLRequest(emptyList())
|
||||
request.addOption("--print", "%(formats)s")
|
||||
request.addOption("-a", urlsFile.absolutePath)
|
||||
request.addOption("--skip-download")
|
||||
request.addOption("-R", "1")
|
||||
request.addOption("--socket-timeout", "5")
|
||||
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||
if (cookiesFile.exists()){
|
||||
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||
}
|
||||
|
||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request){ progress, _, line ->
|
||||
val formats = mutableListOf<Format>()
|
||||
val listOfStrings = JSONArray(line)
|
||||
for (f in 0 until listOfStrings.length()){
|
||||
val format = listOfStrings.get(f) as JSONObject
|
||||
try{
|
||||
if (format.getString("filesize") == "None") continue
|
||||
}catch (e: Exception) { continue }
|
||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||
if (formatProper.filesize > 0){
|
||||
if ( !formatProper.format_note.contains("audio only", true)) {
|
||||
formatProper.format_note = format.getString("format_note")
|
||||
}else{
|
||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||
}
|
||||
formatProper.container = format.getString("ext")
|
||||
formats.add(formatProper)
|
||||
}
|
||||
}
|
||||
progress(formats)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Looper.prepare().run {
|
||||
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
e.printStackTrace()
|
||||
}
|
||||
urlsFile.delete()
|
||||
}
|
||||
|
||||
fun getFromYTDL(query: String): ArrayList<ResultItem?> {
|
||||
init()
|
||||
items = ArrayList()
|
||||
|
|
|
|||
5
app/src/main/res/drawable/baseline_recommend_24.xml
Normal file
5
app/src/main/res/drawable/baseline_recommend_24.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="?android:colorAccent" android:pathData="M12,2a10,10 0,1 0,10 10A10,10 0,0 0,12 2zM18,11.8a0.9,0.9 0,0 1,-0.1 0.5l-2.1,4.9a1.34,1.34 0,0 1,-1.3 0.8L9,18a2,2 0,0 1,-2 -2v-5a1.28,1.28 0,0 1,0.4 -1L12,5l0.69,0.69a1.08,1.08 0,0 1,0.3 0.7v0.2L12.41,10L17,10a1,1 0,0 1,1 1z"/>
|
||||
</vector>
|
||||
|
|
@ -199,12 +199,14 @@
|
|||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/active_download_cancel"
|
||||
style="?attr/materialIconButtonFilledTonalStyle"
|
||||
style="?attr/materialIconButtonFilledStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
app:cornerRadius="10dp"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:iconTint="?android:textColorPrimary"
|
||||
app:icon="@drawable/ic_cancel"
|
||||
app:iconSize="30dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/codec"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Tertiary"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
|
|
@ -153,10 +153,11 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/file_size"
|
||||
style="@style/Widget.Material3.FloatingActionButton.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:background="?attr/colorPrimaryInverse"
|
||||
android:background="?attr/colorSecondary"
|
||||
android:clickable="false"
|
||||
android:gravity="center"
|
||||
android:minWidth="30dp"
|
||||
|
|
@ -180,6 +181,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:cornerRadius="10dp"
|
||||
app:iconTint="?attr/colorAccent"
|
||||
app:icon="@drawable/ic_video"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@
|
|||
app:showAsAction="ifRoom"
|
||||
android:title="@string/share" />
|
||||
|
||||
<item
|
||||
android:id="@+id/select_all"
|
||||
android:title="@string/select_all"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/invert_selected"
|
||||
android:title="@string/invert_selected"
|
||||
|
|
|
|||
Loading…
Reference in a new issue