fixed sponsorblock not restoring properly
hid navigation bar when opening search view and reshowing it when closing
updated download item data after calling ytdlp so that the user doesnt have to wait. Its parallel
added Persian lang in the app
added socks5 proxy support
pull/137/head
deniscerri 3 years ago
parent c07ffcfad3
commit 59ca614ffd
No known key found for this signature in database
GPG Key ID: 95C43D517D830350

@ -19,6 +19,7 @@ import kotlinx.coroutines.launch
import java.util.*
import java.util.concurrent.Executors
class App : Application() {
override fun onCreate() {
@ -26,7 +27,7 @@ class App : Application() {
instance = this
createNotificationChannels()
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
setDefaultValues()
applicationScope = CoroutineScope(SupervisorJob())
applicationScope.launch((Dispatchers.IO)) {
try {
@ -59,6 +60,21 @@ class App : Application() {
Aria2c.getInstance().init(this)
}
private fun setDefaultValues(){
val SPL = 1
val sp = PreferenceManager.getDefaultSharedPreferences(this)
if (sp.getInt("spl", 0) != SPL) {
PreferenceManager.setDefaultValues(this, R.xml.root_preferences, true)
PreferenceManager.setDefaultValues(this, R.xml.downloading_preferences, true)
PreferenceManager.setDefaultValues(this, R.xml.appearance_preferences, true)
PreferenceManager.setDefaultValues(this, R.xml.processing_preferences, true)
PreferenceManager.setDefaultValues(this, R.xml.folders_preference, true)
PreferenceManager.setDefaultValues(this, R.xml.updating_preferences, true)
sp.edit().putInt("spl", SPL).apply()
}
}
private fun createNotificationChannels() {
val notificationUtil = NotificationUtil(this)
notificationUtil.createNotificationChannel()

@ -207,6 +207,14 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
}
}
searchView?.addTransitionListener { _, _, newState ->
if (newState == SearchView.TransitionState.SHOWING){
mainActivity?.hideBottomNavigation()
}else if (newState == SearchView.TransitionState.HIDING){
mainActivity?.showBottomNavigation()
}
}
mainActivity?.onBackPressedDispatcher?.addCallback(this) {
if (searchView?.isShowing == true) {
searchView?.hide()

@ -32,6 +32,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.forEach
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
@ -215,8 +216,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{
}
}
R.id.download_queue -> {
val intent = Intent(context, DownloadQueueMainFragment::class.java)
startActivity(intent)
findNavController().navigate(R.id.downloadQueueMainFragment)
}
R.id.remove_deleted_history -> {
if(allhistoryList!!.isEmpty()){

@ -4,10 +4,12 @@ import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.os.Environment
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@ -18,7 +20,6 @@ import androidx.preference.PreferenceManager
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.deniscerri.ytdlnis.BuildConfig
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.CookieItem
@ -65,7 +66,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
val navController = findNavController()
val appearance = findPreference<Preference>("appearance")
appearance?.summary = "${getString(R.string.language)}, ${getString(R.string.Theme)}, ${getString(R.string.accents)}"
appearance?.summary = "${if (Build.VERSION.SDK_INT < 33) getString(R.string.language) + ", " else ""}${getString(R.string.Theme)}, ${getString(R.string.accents)}, ${getString(R.string.preferred_search_engine)}"
appearance?.setOnPreferenceClickListener {
navController.navigate(R.id.action_mainSettingsFragment_to_appearanceSettingsFragment)
true
@ -338,34 +339,36 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
//preference restore
if(json.has("settings")){
val prefs = json.getAsJsonArray("settings")
val preferencesKeys = preferences.all.map { it.key }
prefs.forEach {
val key : String = it.asJsonObject.get("key").toString().replace("\"", "")
if (preferencesKeys.contains(key)){
when(it.asJsonObject.get("type").toString().replace("\"", "")){
"String" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "")
editor.putString(key, value)
}
"Boolean" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "").toBoolean()
editor.putBoolean(key, value)
}
"Int" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "").toInt()
editor.putInt(key, value)
}
"HashSet" -> {
val value = hashSetOf(it.asJsonObject.get("value").toString().replace("(\")|(\\[)|(])".toRegex(), ""))
editor.putStringSet(key, value)
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit(commit = true){
clear()
val prefs = json.getAsJsonArray("settings")
val preferencesKeys = preferences.all.map { it.key }
prefs.forEach {
val key : String = it.asJsonObject.get("key").toString().replace("\"", "")
if (preferencesKeys.contains(key)){
when(it.asJsonObject.get("type").toString().replace("\"", "")){
"String" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "")
putString(key, value)
}
"Boolean" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "").toBoolean()
putBoolean(key, value)
}
"Int" -> {
val value = it.asJsonObject.get("value").toString().replace("\"", "").toInt()
putInt(key, value)
}
"HashSet" -> {
val value = it.asJsonObject.get("value").toString().replace("(\")|(\\[)|(])|([ \\t])".toRegex(), "").split(",")
putStringSet(key, value.toHashSet())
}
}
}
}
finalMessage.append("${getString(R.string.settings)}: ${prefs.count()}\n")
}
finalMessage.append("${getString(R.string.settings)}: ${prefs.count()}\n")
}
editor.commit()
//history restore
if(json.has("downloads")){
@ -480,14 +483,14 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
builder.setPositiveButton(
getString(R.string.restart)
) { _: DialogInterface?, _: Int ->
val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
requireContext().startActivity(intent)
val intent: Intent? = requireContext().packageManager
.getLaunchIntentForPackage(requireContext().packageName)
intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
if(json.has("settings")){
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(preferences.getString("app_language", "en")))
}
activity?.finishAffinity()
Runtime.getRuntime().exit(0)
}
// handle the negative button of the alert dialog

@ -540,6 +540,11 @@ class InfoUtil(private val context: Context) {
request.addOption("--cookies", cookiesFile.absolutePath)
}
val proxy = sharedPreferences.getString("proxy", "")
if (proxy!!.isNotBlank()){
request.addOption("--proxy", proxy)
}
YoutubeDL.getInstance().execute(request){ progress, _, line ->
try{
val formats = mutableListOf<Format>()
@ -601,6 +606,11 @@ class InfoUtil(private val context: Context) {
request.addOption("--cookies", cookiesFile.absolutePath)
}
val proxy = sharedPreferences.getString("proxy", "")
if (proxy!!.isNotBlank()){
request.addOption("--proxy", proxy)
}
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
val results: Array<String?> = try {
val lineSeparator = System.getProperty("line.separator")
@ -697,6 +707,11 @@ class InfoUtil(private val context: Context) {
request.addOption("--cookies", cookiesFile.absolutePath)
}
val proxy = sharedPreferences.getString("proxy", "")
if (proxy!!.isNotBlank()){
request.addOption("--proxy", proxy)
}
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
val jsonObject = JSONObject(youtubeDLResponse.out)
@ -836,6 +851,11 @@ class InfoUtil(private val context: Context) {
request.addOption("--cookies", cookiesFile.absolutePath)
}
val proxy = sharedPreferences.getString("proxy", "")
if (proxy!!.isNotBlank()){
request.addOption("--proxy", proxy)
}
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
val results: Array<String?> = try {
val lineSeparator = System.getProperty("line.separator")

@ -147,24 +147,6 @@ class NotificationUtil(var context: Context) {
notificationManager.notify(DOWNLOAD_RESUME_NOTIFICATION_ID, notificationBuilder.build())
}
fun createUpdatingItemNotification(channel: String){
val notificationBuilder = getBuilder(channel)
notificationBuilder
.setContentTitle(context.getString(R.string.updating_download_data))
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
android.R.drawable.stat_sys_download
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.clearActions()
notificationManager.notify(DOWNLOAD_UPDATING_NOTIFICATION_ID, notificationBuilder.build())
}
fun createDownloadFinished(title: String?,
filepath: String?,
channel: String
@ -289,7 +271,6 @@ class NotificationUtil(var context: Context) {
const val DOWNLOAD_FINISHED_CHANNEL_ID = "3"
const val DOWNLOAD_FINISHED_NOTIFICATION_ID = 3
const val DOWNLOAD_RESUME_NOTIFICATION_ID = 4
const val DOWNLOAD_UPDATING_NOTIFICATION_ID = 5
private const val PROGRESS_MAX = 100
private const val PROGRESS_CURR = 0
}

@ -16,6 +16,8 @@ import androidx.work.workDataOf
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
@ -25,6 +27,9 @@ import com.deniscerri.ytdlnis.util.InfoUtil
import com.deniscerri.ytdlnis.util.NotificationUtil
import com.yausername.youtubedl_android.YoutubeDL
import com.yausername.youtubedl_android.YoutubeDLRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File
@ -62,25 +67,9 @@ class DownloadWorker(
repository.setDownloadStatus(downloadItem, DownloadRepository.Status.Active)
}
var wasQuickDownloaded = false
//update item if its incomplete
if (downloadItem.title.isEmpty() || downloadItem.author.isEmpty() || downloadItem.thumb.isEmpty()){
notificationUtil.createUpdatingItemNotification(NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID);
runCatching {
setProgressAsync(workDataOf("progress" to 0, "output" to context.getString(R.string.updating_download_data), "id" to downloadItem.id, "log" to false))
val info = infoUtil.getMissingInfo(downloadItem.url)
if (downloadItem.title.isEmpty()) downloadItem.title = info?.title.toString()
if (downloadItem.author.isEmpty()) downloadItem.author = info?.author.toString()
downloadItem.duration = info?.duration.toString()
downloadItem.website = info?.website.toString()
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info?.thumb.toString()
runBlocking {
wasQuickDownloaded = resultDao.getCountInt() == 0
dao.update(downloadItem)
}
}
notificationUtil.cancelDownloadNotification(NotificationUtil.DOWNLOAD_UPDATING_NOTIFICATION_ID)
CoroutineScope(Dispatchers.IO).launch {
//update item if its incomplete
updateDownloadItem(downloadItem, infoUtil, dao, resultDao)
}
val intent = Intent(context, MainActivity::class.java)
@ -344,7 +333,7 @@ class DownloadWorker(
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
)
if (wasQuickDownloaded){
if (updateDownloadItem(downloadItem, infoUtil, dao, resultDao)){
runCatching {
setProgressAsync(workDataOf("progress" to 100, "output" to "Creating Result Items", "id" to downloadItem.id, "log" to false))
runBlocking {
@ -398,10 +387,30 @@ class DownloadWorker(
)
}
}
return Result.success()
}
private fun updateDownloadItem(downloadItem: DownloadItem, infoUtil: InfoUtil, dao: DownloadDao, resultDao: ResultDao) : Boolean {
var wasQuickDownloaded = false
if (downloadItem.title.isEmpty() || downloadItem.author.isEmpty() || downloadItem.thumb.isEmpty()){
runCatching {
setProgressAsync(workDataOf("progress" to 0, "output" to context.getString(R.string.updating_download_data), "id" to downloadItem.id, "log" to false))
val info = infoUtil.getMissingInfo(downloadItem.url)
if (downloadItem.title.isEmpty()) downloadItem.title = info?.title.toString()
if (downloadItem.author.isEmpty()) downloadItem.author = info?.author.toString()
downloadItem.duration = info?.duration.toString()
downloadItem.website = info?.website.toString()
if (downloadItem.thumb.isEmpty()) downloadItem.thumb = info?.thumb.toString()
runBlocking {
wasQuickDownloaded = resultDao.getCountInt() == 0
dao.update(downloadItem)
}
}
}
return wasQuickDownloaded
}
override fun onStopped() {
YoutubeDL.getInstance().destroyProcessById(itemId.toInt().toString())
super.onStopped()

@ -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="M19.5,10c0.17,0 0.33,0.03 0.5,0.05L20,1L1,20h13v-3c0,-0.89 0.39,-1.68 1,-2.23v-0.27c0,-2.48 2.02,-4.5 4.5,-4.5zM22,16v-1.5c0,-1.38 -1.12,-2.5 -2.5,-2.5S17,13.12 17,14.5L17,16c-0.55,0 -1,0.45 -1,1v4c0,0.55 0.45,1 1,1h5c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1zM21,16h-3v-1.5c0,-0.83 0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5L21,16z"/>
</vector>

@ -95,6 +95,7 @@
<item>bn</item>
<item>de</item>
<item>es</item>
<item>fa</item>
<item>fr</item>
<item>in</item>
<item>it</item>

@ -50,11 +50,11 @@
<string name="limit_rate_summary">Maximum download rate (in bytes per second), e.g. 50K or 4.2M</string>
<string name="aria2_summary">Use aria2c as downloader instead of the default</string>
<string name="processing">Processing</string>
<string name="embed_subs_summary">Adds subtitles in the video</string>
<string name="embed_subs_summary">Add subtitles in the video</string>
<string name="embed_thumb">Thumbnail Covers</string>
<string name="embed_thumb_summary">Uses the thumbnail as cover art</string>
<string name="embed_thumb_summary">Use the thumbnail as cover art</string>
<string name="add_chapters">Chapters in Videos</string>
<string name="add_chapters_summary">Marks YouTube / SponsorBlock segments as chapters for the video</string>
<string name="add_chapters_summary">Mark YouTube / SponsorBlock segments as chapters for the video</string>
<string name="save_thumb">Save Thumbnail</string>
<string name="save_thumb_summary">Save the thumbnail in the download folder</string>
<string name="audio_format">Audio Format</string>
@ -66,13 +66,13 @@
<string name="command_download_notification_channel_name">Command Downloads</string>
<string name="command_download_notification_channel_description">Notification showing the progress of downloading using a yt-dlp command</string>
<string name="items_left">item(s) left</string>
<string name="history_is_empty">History empty.</string>
<string name="history_is_empty">History is empty.</string>
<string name="you_are_going_to_delete">Deleting</string>
<string name="url">URL</string>
<string name="link_copied_to_clipboard">Link copied to clipboard</string>
<string name="api_key">Use API Key</string>
<string name="api_key_summary">Faster results from YouTube</string>
<string name="update_app_summary">Announces new versions of the app when it is opened</string>
<string name="update_app_summary">Announce new versions of the app when it is opened</string>
<string name="downloads">Downloads</string>
<string name="remove_deleted">Remove Deleted</string>
<string name="remove_duplicates">Remove Duplicates</string>
@ -260,4 +260,6 @@
<string name="backup_created_successfully">Backup file saved in the downloads folder</string>
<string name="appearance">Appearance</string>
<string name="backup_restore">Backup And Restore</string>
<string name="socks5_proxy_summary">Use the specified HTTP/HTTPS/SOCKS proxy</string>
<string name="socks5_proxy">Socks5 Proxy URL</string>
</resources>

@ -35,6 +35,13 @@
app:summary="@string/download_over_metered_networks_summary"
app:title="@string/download_over_metered_networks" />
<EditTextPreference
android:icon="@drawable/baseline_network_locked_24"
app:key="proxy"
app:defaultValue=""
app:summary="@string/socks5_proxy_summary"
app:title="@string/socks5_proxy" />
<ListPreference
android:dependency="download_card"
android:defaultValue="video"

@ -6,6 +6,7 @@
<locale android:name="bn"/>
<locale android:name="de"/>
<locale android:name="es"/>
<locale android:name="fa-IR"/>
<locale android:name="fr"/>
<locale android:name="in"/>
<locale android:name="it"/>
@ -13,12 +14,12 @@
<locale android:name="lv"/>
<locale android:name="nb-NO"/>
<locale android:name="pl"/>
<locale android:name="pt_BR" />
<locale android:name="pt-BR" />
<locale android:name="ru"/>
<locale android:name="ro_RO"/>
<locale android:name="ro-RO"/>
<locale android:name="sq-AL"/>
<locale android:name="tr-TR"/>
<locale android:name="ta_IN"/>
<locale android:name="ta-IN"/>
<locale android:name="uk"/>
<locale android:name="vi"/>
<locale android:name="zh-CN"/>

Loading…
Cancel
Save