From 59ca614ffd33b1aa21ece383ae66c8a7b20cf3c1 Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Fri, 19 May 2023 22:12:31 +0200 Subject: [PATCH] stuff 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 --- .../main/java/com/deniscerri/ytdlnis/App.kt | 18 +++++- .../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 8 +++ .../ytdlnis/ui/downloads/HistoryFragment.kt | 4 +- .../ui/more/settings/MainSettingsFragment.kt | 61 ++++++++++--------- .../com/deniscerri/ytdlnis/util/InfoUtil.kt | 20 ++++++ .../ytdlnis/util/NotificationUtil.kt | 19 ------ .../deniscerri/ytdlnis/work/DownloadWorker.kt | 51 +++++++++------- .../drawable/baseline_network_locked_24.xml | 5 ++ app/src/main/res/values/arrays.xml | 1 + app/src/main/res/values/strings.xml | 12 ++-- .../main/res/xml/downloading_preferences.xml | 7 +++ app/src/main/res/xml/locales_config.xml | 7 ++- 12 files changed, 133 insertions(+), 80 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_network_locked_24.xml diff --git a/app/src/main/java/com/deniscerri/ytdlnis/App.kt b/app/src/main/java/com/deniscerri/ytdlnis/App.kt index 0ff29621..280cc8df 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/App.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/App.kt @@ -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() 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 856a667e..82df5f43 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -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() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt index 39f848a0..578b976f 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/HistoryFragment.kt @@ -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()){ diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/MainSettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/MainSettingsFragment.kt index 8eda9b0b..507ab9bf 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/MainSettingsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/MainSettingsFragment.kt @@ -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("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 diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt index 4dfdc5e5..f1d122b5 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt @@ -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() @@ -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 = 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 = try { val lineSeparator = System.getProperty("line.separator") diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt index 05a5c2c3..124bc9df 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/NotificationUtil.kt @@ -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 } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt index f0de08b2..415b4049 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -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() diff --git a/app/src/main/res/drawable/baseline_network_locked_24.xml b/app/src/main/res/drawable/baseline_network_locked_24.xml new file mode 100644 index 00000000..85025449 --- /dev/null +++ b/app/src/main/res/drawable/baseline_network_locked_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index b9584b19..fa1fb8cb 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -95,6 +95,7 @@ bn de es + fa fr in it diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0cd22a02..9c3dc186 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,11 +50,11 @@ Maximum download rate (in bytes per second), e.g. 50K or 4.2M Use aria2c as downloader instead of the default Processing - Adds subtitles in the video + Add subtitles in the video Thumbnail Covers - Uses the thumbnail as cover art + Use the thumbnail as cover art Chapters in Videos - Marks YouTube / SponsorBlock segments as chapters for the video + Mark YouTube / SponsorBlock segments as chapters for the video Save Thumbnail Save the thumbnail in the download folder Audio Format @@ -66,13 +66,13 @@ Command Downloads Notification showing the progress of downloading using a yt-dlp command item(s) left - History empty. + History is empty. Deleting URL Link copied to clipboard Use API Key Faster results from YouTube - Announces new versions of the app when it is opened + Announce new versions of the app when it is opened Downloads Remove Deleted Remove Duplicates @@ -260,4 +260,6 @@ Backup file saved in the downloads folder Appearance Backup And Restore + Use the specified HTTP/HTTPS/SOCKS proxy + Socks5 Proxy URL \ No newline at end of file diff --git a/app/src/main/res/xml/downloading_preferences.xml b/app/src/main/res/xml/downloading_preferences.xml index 4150ba7e..bdef0624 100644 --- a/app/src/main/res/xml/downloading_preferences.xml +++ b/app/src/main/res/xml/downloading_preferences.xml @@ -35,6 +35,13 @@ app:summary="@string/download_over_metered_networks_summary" app:title="@string/download_over_metered_networks" /> + + + @@ -13,12 +14,12 @@ - + - + - +