From 236f83d161a85218bf0e1cf357e767804dc30e82 Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Sat, 9 Sep 2023 12:15:07 +0200 Subject: [PATCH] stuff added auto preferred download type Show collected file size in multi download card fixed app chossing worst format and not best fixed update util not working in release fixed ytm playlists not loading fixed sponsorblock not being checked in multiple download card added playlist and playlist index metadata in download items added -a txt path if preferred download type is command or if the txt file is shared in terminal fixed app cancelling workmanager earlier than expected added title and author sync between audio and video frgaments --- app/src/main/AndroidManifest.xml | 2 - .../com/deniscerri/ytdlnis/MainActivity.kt | 51 +++++--- .../ytdlnis/adapter/ActiveDownloadAdapter.kt | 1 + .../ytdlnis/adapter/DownloadLogsAdapter.kt | 1 + .../ytdlnis/database/models/DownloadItem.kt | 2 +- .../ytdlnis/database/models/GithubRelease.kt | 7 + .../database/viewmodel/DownloadViewModel.kt | 28 +++- .../database/viewmodel/ResultViewModel.kt | 7 +- .../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 4 +- .../ConfigureDownloadBottomSheetDialog.kt | 75 +++++++---- .../ui/downloadcard/DownloadAudioFragment.kt | 14 +- .../downloadcard/DownloadBottomSheetDialog.kt | 120 ++++++++++++------ .../downloadcard/DownloadCommandFragment.kt | 55 +++++--- .../DownloadMultipleBottomSheetDialog.kt | 19 +++ .../ui/downloadcard/DownloadVideoFragment.kt | 13 +- .../ui/downloadcard/TitleAuthorSync.kt | 5 + .../ytdlnis/ui/more/TerminalActivity.kt | 13 +- .../com/deniscerri/ytdlnis/util/FileUtil.kt | 8 +- .../com/deniscerri/ytdlnis/util/InfoUtil.kt | 42 ++++-- .../com/deniscerri/ytdlnis/util/UiUtil.kt | 9 +- .../com/deniscerri/ytdlnis/util/UpdateUtil.kt | 18 ++- .../deniscerri/ytdlnis/work/DownloadWorker.kt | 3 - .../layout/download_multiple_bottom_sheet.xml | 14 ++ .../res/layout/fragment_download_command.xml | 1 + app/src/main/res/layout/textview.xml | 9 ++ app/src/main/res/values-bn-rIN/strings.xml | 1 - app/src/main/res/values-jv/strings.xml | 1 - app/src/main/res/values/arrays.xml | 3 + .../main/res/xml/downloading_preferences.xml | 2 +- 29 files changed, 375 insertions(+), 153 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/TitleAuthorSync.kt create mode 100644 app/src/main/res/layout/textview.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e1b2cd3a..116c926e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,9 +56,7 @@ android:theme="@style/Theme.BottomSheet"> - - diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt index d7fdcf7a..126d0756 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt @@ -18,6 +18,7 @@ import android.view.View import android.view.WindowInsets import android.widget.CheckBox import android.widget.TextView +import android.widget.Toast import androidx.annotation.RequiresApi import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.app.ActivityCompat @@ -39,7 +40,9 @@ import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel import com.deniscerri.ytdlnis.ui.BaseActivity import com.deniscerri.ytdlnis.ui.HomeFragment +import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog import com.deniscerri.ytdlnis.ui.more.settings.SettingsActivity +import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.ThemeUtil import com.deniscerri.ytdlnis.util.UpdateUtil import com.google.android.material.bottomnavigation.BottomNavigationView @@ -54,8 +57,10 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import java.io.BufferedReader +import java.io.File import java.io.InputStreamReader import java.io.Reader +import java.net.URI import java.nio.charset.Charset import java.nio.charset.StandardCharsets import kotlin.system.exitProcess @@ -332,26 +337,38 @@ class MainActivity : BaseActivity() { }else{ intent.getParcelableExtra(Intent.EXTRA_STREAM) } - val `is` = contentResolver.openInputStream(uri!!) - val textBuilder = StringBuilder() - val reader: Reader = BufferedReader( - InputStreamReader( - `is`, Charset.forName( - StandardCharsets.UTF_8.name() + + if (preferences.getString("preferred_download_type", "video") == "command"){ + val f = File(FileUtil.formatPath(uri?.path ?: "")) + if (!f.exists()){ + Toast.makeText(context, "Couldn't read file", Toast.LENGTH_LONG).show() + return + } + val item = downloadViewModel.createEmptyResultItem(f.absolutePath) + val bottomSheet = DownloadBottomSheetDialog(item, DownloadViewModel.Type.command, null, true) + bottomSheet.show(supportFragmentManager, "downloadSingleSheet") + }else{ + val `is` = contentResolver.openInputStream(uri!!) + val textBuilder = StringBuilder() + val reader: Reader = BufferedReader( + InputStreamReader( + `is`, Charset.forName( + StandardCharsets.UTF_8.name() + ) ) ) - ) - var c: Int - while (reader.read().also { c = it } != -1) { - textBuilder.append(c.toChar()) + var c: Int + while (reader.read().also { c = it } != -1) { + textBuilder.append(c.toChar()) + } + val bundle = Bundle() + bundle.putString("url", textBuilder.toString()) + navController.popBackStack(R.id.homeFragment, true) + navController.navigate( + R.id.homeFragment, + bundle + ) } - val bundle = Bundle() - bundle.putString("url", textBuilder.toString()) - navController.popBackStack(R.id.homeFragment, true) - navController.navigate( - R.id.homeFragment, - bundle - ) } catch (e: Exception) { e.printStackTrace() } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt index 7ef835dc..8dc50782 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt @@ -104,6 +104,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: DownloadViewModel.Type.audio -> type.setIconResource(R.drawable.ic_music) DownloadViewModel.Type.video -> type.setIconResource(R.drawable.ic_video) DownloadViewModel.Type.command -> type.setIconResource(R.drawable.ic_terminal) + else -> {} } val formatDetailsChip = card.findViewById(R.id.format_note) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/DownloadLogsAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/DownloadLogsAdapter.kt index 6f1a6d89..6f5c972e 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/DownloadLogsAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/DownloadLogsAdapter.kt @@ -66,6 +66,7 @@ class DownloadLogsAdapter(onItemClickListener: OnItemClickListener, activity: Ac DownloadViewModel.Type.audio -> downloadTypeIcon.setIconResource(R.drawable.ic_music) DownloadViewModel.Type.video -> downloadTypeIcon.setIconResource(R.drawable.ic_video) DownloadViewModel.Type.command -> downloadTypeIcon.setIconResource(R.drawable.ic_terminal) + else -> {} } val formatNote = card.findViewById(R.id.format_note) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt index bc34fd41..4b29f743 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt @@ -9,7 +9,7 @@ import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel data class DownloadItem( @PrimaryKey(autoGenerate = true) var id: Long, - val url: String, + var url: String, var title: String, var author: String, var thumb: String, diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/GithubRelease.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/GithubRelease.kt index 6095dadc..5b132242 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/GithubRelease.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/GithubRelease.kt @@ -1,13 +1,20 @@ package com.deniscerri.ytdlnis.database.models +import com.google.gson.annotations.SerializedName + data class GithubRelease( + @SerializedName(value = "tag_name") var tag_name: String, + @SerializedName(value = "body") var body: String, + @SerializedName(value = "assets") var assets: List ) data class GithubReleaseAsset( + @SerializedName(value = "name") var name: String, + @SerializedName(value = "browser_download_url") var browser_download_url: String ) \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt index 61d06925..8deab4ea 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/DownloadViewModel.kt @@ -85,9 +85,15 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application private val dao: DownloadDao enum class Type { - audio, video, command + auto, audio, video, command } + private val urlsForAudioType = listOf( + "music", + "audio", + "soundcloud" + ) + init { dbManager = DBManager.getInstance(application) dao = dbManager.downloadDao @@ -194,6 +200,13 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application return repository.getItemByID(id) } + private fun getSuitableDownloadType(url: String): Type{ + if (urlsForAudioType.any { url.contains(it) }){ + return Type.audio + } + return Type.video + } + fun createDownloadItemFromResult(resultItem: ResultItem, givenType: Type) : DownloadItem { val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false) val saveSubs = sharedPreferences.getBoolean("write_subtitles", false) @@ -202,6 +215,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false) var type = givenType + if (type == Type.auto){ + type = getSuitableDownloadType(resultItem.url) + } if(type == Type.command && commandTemplateDao.getTotalNumber() == 0) type = Type.video val customFileNameTemplate = when(type) { @@ -320,6 +336,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application Type.audio -> sharedPreferences.getString("music_path", FileUtil.getDefaultAudioPath())!! Type.video -> sharedPreferences.getString("video_path", FileUtil.getDefaultVideoPath())!! Type.command -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())!! + else -> "" } list.forEach { @@ -329,6 +346,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application Type.audio -> sharedPreferences.getString("music_path", FileUtil.getDefaultAudioPath()) Type.video -> sharedPreferences.getString("video_path", FileUtil.getDefaultVideoPath()) Type.command -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath()) + else -> "" } if (it.downloadPath == currentDownloadPath) it.downloadPath = updatedDownloadPath @@ -359,6 +377,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application Type.audio -> FileUtil.getDefaultAudioPath() Type.video -> FileUtil.getDefaultVideoPath() Type.command -> FileUtil.getDefaultCommandPath() + else -> "" } val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet()) @@ -404,7 +423,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application Type.video -> { return cloneFormat( try { - val theFormats = formats.filter { !it.format_note.contains("audio", true) }.sortedBy { it.format_id }.ifEmpty { defaultVideoFormats } + val theFormats = formats.filter { !it.format_note.contains("audio", true) }.sortedBy { it.format_id }.ifEmpty { defaultVideoFormats }.sortedByDescending { it.filesize } when (videoQualityPreference) { "worst" -> { theFormats.first() @@ -416,7 +435,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application requirements.add { it: Format -> it.format_note.contains(videoQualityPreference.substring(0, videoQualityPreference.length - 1)) } requirements.add { it: Format -> it.vcodec.startsWith(videoCodec!!, true) } - theFormats.reversed().maxByOrNull { f -> requirements.count{ req -> req(f)} } ?: throw Exception() + theFormats.maxByOrNull { f -> requirements.count{ req -> req(f)} } ?: throw Exception() } } }catch (e: Exception){ @@ -468,8 +487,9 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application fun turnResultItemsToDownloadItems(items: List) : List { val list : MutableList = mutableListOf() - val preferredType = sharedPreferences.getString("preferred_download_type", "video") + var preferredType = sharedPreferences.getString("preferred_download_type", "video") items.forEach { + if (preferredType == Type.auto.toString()) preferredType = getSuitableDownloadType(it!!.url).toString() list.add(createDownloadItemFromResult(it!!, Type.valueOf(preferredType!!))) } return list diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt index 9b0b2e08..e5f234f1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt @@ -3,6 +3,7 @@ package com.deniscerri.ytdlnis.database.viewmodel import android.app.Application import android.content.SharedPreferences import android.util.Log +import android.util.Patterns import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData @@ -111,14 +112,14 @@ class ResultViewModel(application: Application) : AndroidViewModel(application) } private fun getQueryType(inputQuery: String) : String { var type = "Search" - val p = Pattern.compile("(^(https?)://(www.)?(music.)?youtu(.be)?)|(^(https?)://(www.)?piped.video)") + val p = Pattern.compile("(^(https?)://(www.)?youtu(.be)?)|(^(https?)://(www.)?piped.video)") val m = p.matcher(inputQuery) if (m.find()) { type = "YT_Video" - if (inputQuery.contains("playlist?list=") && !inputQuery.contains("music.youtu")) { + if (inputQuery.contains("playlist?list=")) { type = "YT_Playlist" } - } else if (inputQuery.contains("http")) { + } else if (Patterns.WEB_URL.matcher(inputQuery).matches()) { type = "Default" } return type diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt index a0239791..cfe0b4fa 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -159,7 +159,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene homeAdapter!!.submitList(it) resultsList = it if(resultViewModel.repository.itemCount.value > 1 || resultViewModel.repository.itemCount.value == -1){ - if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && it[0].playlistTitle != getString(R.string.trendingPlaylist) && !loadingItems){ + if (it.size > 1 && it[0].playlistTitle.isNotEmpty() && !loadingItems){ downloadAllFabCoordinator!!.visibility = VISIBLE }else{ downloadAllFabCoordinator!!.visibility = GONE @@ -187,7 +187,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene recyclerView?.setPadding(0,0,0,100) shimmerCards!!.stopShimmer() shimmerCards!!.visibility = GONE - if (resultsList!!.size > 1 && resultsList!![0]!!.playlistTitle.isNotEmpty() && resultsList!![0]!!.playlistTitle != getString(R.string.trendingPlaylist)){ + if (resultsList!!.size > 1 && resultsList!![0]!!.playlistTitle.isNotEmpty()){ downloadAllFabCoordinator!!.visibility = VISIBLE }else{ downloadAllFabCoordinator!!.visibility = GONE diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt index ac4fbfd2..f13fe9b1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/ConfigureDownloadBottomSheetDialog.kt @@ -11,6 +11,7 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.Toast +import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView @@ -64,7 +65,6 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri super.setupDialog(dialog, style) val view = LayoutInflater.from(context).inflate(R.layout.configure_download_bottom_sheet, null) dialog.setContentView(view) - dialog.setOnShowListener { behavior = BottomSheetBehavior.from(view.parent as View) val displayMetrics = DisplayMetrics() @@ -80,7 +80,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri overScrollMode = View.OVER_SCROLL_NEVER } - val fragments = mutableListOf( + val fragments = mutableListOf( DownloadAudioFragment(resultItem, downloadItem), DownloadVideoFragment(resultItem, downloadItem) ) @@ -161,6 +161,9 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri viewPager2.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { tabLayout.selectTab(tabLayout.getTabAt(position)) + runCatching { + updateTitleAuthorWhenSwitching() + } } }) @@ -168,22 +171,7 @@ class ConfigureDownloadBottomSheetDialog(private val resultItem: ResultItem, pri val ok = view.findViewById