From 78a80a734d4633663b8ab5e41cccd8c06023d201 Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Fri, 31 Mar 2023 23:07:36 +0200 Subject: [PATCH] added ignore battery optimization and other small stuff --- app/build.gradle | 8 +- app/src/main/AndroidManifest.xml | 1 + .../com/deniscerri/ytdlnis/MainActivity.kt | 1 + .../ytdlnis/adapter/ActiveDownloadAdapter.kt | 6 + .../ytdlnis/adapter/GenericDownloadAdapter.kt | 2 +- .../ui/downloads/ActiveDownloadsFragment.kt | 14 ++ .../ui/downloads/ErroredDownloadsFragment.kt | 2 +- .../ytdlnis/ui/downloads/HistoryFragment.kt | 20 ++- .../ui/more/settings/SettingsFragment.kt | 22 +++ .../com/deniscerri/ytdlnis/util/FileUtil.kt | 6 + .../deniscerri/ytdlnis/work/DownloadWorker.kt | 5 +- app/src/main/res/drawable/ic_battery.xml | 5 + .../main/res/layout/active_download_card.xml | 12 +- .../res/layout/activity_download_queue.xml | 1 + .../main/res/layout/download_bottom_sheet.xml | 17 +- app/src/main/res/layout/download_card.xml | 1 + app/src/main/res/layout/fragment_history.xml | 164 +++++++++--------- app/src/main/res/layout/generic_toolbar.xml | 22 +++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/root_preferences.xml | 5 + build.gradle | 2 +- 21 files changed, 211 insertions(+), 106 deletions(-) create mode 100644 app/src/main/res/drawable/ic_battery.xml create mode 100644 app/src/main/res/layout/generic_toolbar.xml diff --git a/app/build.gradle b/app/build.gradle index 1a8fe3a0..9475301a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -154,10 +154,10 @@ dependencies { implementation "androidx.work:work-runtime-ktx:$workVer" - implementation "androidx.room:room-runtime:2.5.0" - implementation "androidx.room:room-ktx:2.5.0" - kapt "androidx.room:room-compiler:2.5.0" - androidTestImplementation "androidx.room:room-testing:2.5.0" + implementation "androidx.room:room-runtime:2.5.1" + implementation "androidx.room:room-ktx:2.5.1" + kapt "androidx.room:room-compiler:2.5.1" + androidTestImplementation "androidx.room:room-testing:2.5.1" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' implementation "androidx.compose.runtime:runtime:$composeVer" androidTestImplementation "com.google.truth:truth:1.1.3" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0e89ffa6..c700f689 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,6 +12,7 @@ + { + //navController.navigate(R.id.settingsFragment) val intent = Intent(context, SettingsActivity::class.java) startActivity(intent) } 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 e18bb6ac..91436291 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/ActiveDownloadAdapter.kt @@ -16,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.util.FileUtil +import com.google.android.exoplayer2.offline.Download import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.progressindicator.LinearProgressIndicator @@ -114,6 +115,10 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: val output = card.findViewById(R.id.output) output.tag = "${item.id}##output" + output.setOnClickListener { + onItemClickListener.onOutputClick(item) + } + // CANCEL BUTTON ---------------------------------- val cancelButton = card.findViewById(R.id.active_download_cancel) @@ -125,6 +130,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity: } interface OnItemClickListener { fun onCancelClick(itemID: Long) + fun onOutputClick(item: DownloadItem) } companion object { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt index a54f7cf4..62fedf89 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt @@ -108,7 +108,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: DownloadRepository.Status.Queued.toString() -> actionButton.setIconResource(R.drawable.ic_baseline_delete_outline_24) else -> { actionButton.setIconResource(R.drawable.ic_baseline_file_open_24) - val logFile = File(activity.filesDir.absolutePath + """/logs/${item.id} - ${item.title}##${item.type}##${item.format.format_id}.log""") + val logFile = fileUtil.getLogFile(activity, item) if (!logFile.exists()){ actionButton.visibility = View.GONE } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt index 98b676c7..bedd6f03 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ActiveDownloadsFragment.kt @@ -1,6 +1,7 @@ package com.deniscerri.ytdlnis.ui.downloads import android.app.Activity +import android.content.Intent import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater @@ -19,6 +20,8 @@ import com.deniscerri.ytdlnis.adapter.ActiveDownloadAdapter import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding +import com.deniscerri.ytdlnis.ui.more.downloadLogs.DownloadLogActivity +import com.deniscerri.ytdlnis.util.FileUtil import com.deniscerri.ytdlnis.util.NotificationUtil import com.google.android.material.progressindicator.LinearProgressIndicator import com.yausername.youtubedl_android.YoutubeDL @@ -33,6 +36,7 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL private lateinit var activeDownloads : ActiveDownloadAdapter lateinit var downloadItem: DownloadItem private lateinit var notificationUtil: NotificationUtil + private lateinit var fileUtil: FileUtil override fun onCreateView( @@ -44,6 +48,7 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false) activity = getActivity() notificationUtil = NotificationUtil(requireContext()) + fileUtil = FileUtil() downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java] return fragmentView } @@ -101,6 +106,15 @@ class ActiveDownloadsFragment() : Fragment(), ActiveDownloadAdapter.OnItemClickL cancelDownload(itemID) } + override fun onOutputClick(item: DownloadItem) { + val logFile = fileUtil.getLogFile(requireContext(), item) + if (logFile.exists()) { + val intent = Intent(requireContext(), DownloadLogActivity::class.java) + intent.putExtra("path", logFile.absolutePath) + startActivity(intent) + } + } + private fun cancelDownload(itemID: Long){ val id = itemID.toInt() YoutubeDL.getInstance().destroyProcessById(id.toString()) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt index 8052ecb5..d0721bfd 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/ErroredDownloadsFragment.kt @@ -87,7 +87,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL override fun onActionButtonClick(itemID: Long) { val item = items.find { it.id == itemID } ?: return - val file = File(requireContext().filesDir.absolutePath + """/logs/${item.id} - ${item.title}##${item.type}##${item.format.format_id}.log""") + val file = fileUtil.getLogFile(requireContext(), item) val intent = Intent(requireContext(), DownloadLogActivity::class.java) intent.putExtra("path", file.absolutePath) startActivity(intent) 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 317a6e66..0f8db793 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 @@ -17,6 +17,9 @@ import androidx.appcompat.widget.SearchView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController +import androidx.navigation.ui.AppBarConfiguration +import androidx.navigation.ui.setupWithNavController import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -242,10 +245,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ private fun changeSortIcon(item: TextView, order: HistorySort){ when(order){ HistorySort.DESC ->{ - item.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_up, 0,0,0) + item.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_up, 0,0,0) } HistorySort.ASC -> { - item.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_down, 0,0,0) + item.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_down, 0,0,0) } } } @@ -264,7 +267,7 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ val filesize = sortSheet!!.findViewById(R.id.filesize) val sortOptions = listOf(date!!, title!!, author!!, filesize!!) - sortOptions.forEach { it.setCompoundDrawablesWithIntrinsicBounds(R.drawable.empty,0,0,0) } + sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) } when(historyViewModel.sortType.value!!) { HistoryRepository.HistorySortType.DATE -> changeSortIcon(date, historyViewModel.sortOrder.value!!) HistoryRepository.HistorySortType.TITLE -> changeSortIcon(title, historyViewModel.sortOrder.value!!) @@ -273,22 +276,22 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ } date.setOnClickListener { - sortOptions.forEach { it.setCompoundDrawablesWithIntrinsicBounds(R.drawable.empty,0,0,0) } + sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) } historyViewModel.setSorting(HistoryRepository.HistorySortType.DATE) changeSortIcon(date, historyViewModel.sortOrder.value!!) } title.setOnClickListener { - sortOptions.forEach { it.setCompoundDrawablesWithIntrinsicBounds(R.drawable.empty,0,0,0) } + sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) } historyViewModel.setSorting(HistoryRepository.HistorySortType.TITLE) changeSortIcon(title, historyViewModel.sortOrder.value!!) } author.setOnClickListener { - sortOptions.forEach { it.setCompoundDrawablesWithIntrinsicBounds(R.drawable.empty,0,0,0) } + sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) } historyViewModel.setSorting(HistoryRepository.HistorySortType.AUTHOR) changeSortIcon(author, historyViewModel.sortOrder.value!!) } filesize.setOnClickListener { - sortOptions.forEach { it.setCompoundDrawablesWithIntrinsicBounds(R.drawable.empty,0,0,0) } + sortOptions.forEach { it.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.empty,0,0,0) } historyViewModel.setSorting(HistoryRepository.HistorySortType.FILESIZE) changeSortIcon(filesize, historyViewModel.sortOrder.value!!) } @@ -332,9 +335,10 @@ class HistoryFragment : Fragment(), HistoryAdapter.OnItemClickListener{ val websites = mutableListOf() val websiteFilter = historyViewModel.websiteFilter.value for (item in list){ - if (!websites.contains(item.website)) websites.add(item.website) + if (!websites.contains(item.website.lowercase())) websites.add(item.website.lowercase()) } websiteGroup!!.removeAllViews() + if (websites.size <= 1) return //val websites = historyRecyclerViewAdapter!!.websites for (i in websites.indices) { val w = websites[i] diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/SettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/SettingsFragment.kt index 96229bcf..b761e68a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/SettingsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/SettingsFragment.kt @@ -1,15 +1,19 @@ package com.deniscerri.ytdlnis.ui.more.settings import android.app.Activity +import android.content.Context +import android.content.Context.POWER_SERVICE import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Environment +import android.os.PowerManager import android.provider.Settings import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatDelegate +import androidx.core.content.ContextCompat.getSystemService import androidx.core.os.LocaleListCompat import androidx.lifecycle.lifecycleScope import androidx.preference.* @@ -26,8 +30,10 @@ import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import java.util.* + class SettingsFragment : PreferenceFragmentCompat() { private var language: ListPreference? = null + private var ignoreBatteryOptimization: Preference? = null private var musicPath: Preference? = null private var videoPath: Preference? = null private var commandPath: Preference? = null @@ -90,6 +96,7 @@ class SettingsFragment : PreferenceFragmentCompat() { requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) val editor = preferences.edit() language = findPreference("app_language") + ignoreBatteryOptimization = findPreference("ignore_battery") musicPath = findPreference("music_path") videoPath = findPreference("video_path") commandPath = findPreference("command_path") @@ -140,6 +147,12 @@ class SettingsFragment : PreferenceFragmentCompat() { val lang = if (values.contains(Locale.getDefault().language)) Locale.getDefault().language else "en" editor.putString("app_language", lang) + val packageName: String = requireContext().packageName + val pm = requireContext().applicationContext.getSystemService(POWER_SERVICE) as PowerManager + if (pm.isIgnoringBatteryOptimizations(packageName)) { + ignoreBatteryOptimization!!.isVisible = false + } + if (preferences.getString("music_path", "")!!.isEmpty()) { editor.putString("music_path", getString(R.string.music_path)) } @@ -197,6 +210,15 @@ class SettingsFragment : PreferenceFragmentCompat() { true } + ignoreBatteryOptimization!!.onPreferenceClickListener = + Preference.OnPreferenceClickListener { + val intent = Intent() + intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + intent.data = Uri.parse("package:" + requireContext().packageName) + startActivity(intent) + true + } + musicPath!!.summary = fileUtil?.formatPath(preferences.getString("music_path", "")!!) musicPath!!.onPreferenceClickListener = Preference.OnPreferenceClickListener { diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt index f5345e3f..4d6341a3 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt @@ -7,6 +7,7 @@ import android.os.Build import android.provider.DocumentsContract import android.webkit.MimeTypeMap import com.deniscerri.ytdlnis.R +import com.deniscerri.ytdlnis.database.models.DownloadItem import okhttp3.internal.closeQuietly import java.io.File import java.net.URLDecoder @@ -135,6 +136,11 @@ class FileUtil() { return scanMedia(fileList, context) } + fun getLogFile(context: Context, item: DownloadItem) : File { + val titleRegex = Regex("[^A-Za-z\\d ]") + return File(context.filesDir.absolutePath + """/logs/${item.id} - ${titleRegex.replace(item.title, "")}##${item.type}##${item.format.format_id}.log""") + } + fun convertFileSize(s: Long): String{ if (s <= 0) return "?" val units = arrayOf("B", "kB", "MB", "GB", "TB") 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 d61a7c3e..6a067b43 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -36,6 +36,7 @@ class DownloadWorker( if (itemId == 0L) return Result.failure() val notificationUtil = NotificationUtil(context) + val fileUtil = FileUtil() val dbManager = DBManager.getInstance(context) val dao = dbManager.downloadDao val repository = DownloadRepository(dao) @@ -225,10 +226,9 @@ class DownloadWorker( } } - val titleRegex = Regex("[^A-Za-z\\d ]") val logDownloads = sharedPreferences.getBoolean("log_downloads", false) && !sharedPreferences.getBoolean("incognito", false) val logFolder = File(context.filesDir.absolutePath + "/logs") - val logFile = File(context.filesDir.absolutePath + """/logs/${downloadItem.id} - ${titleRegex.replace(downloadItem.title, "")}##${downloadItem.type}##${downloadItem.format.format_id}.log""") + val logFile = fileUtil.getLogFile(context, downloadItem) runCatching { if (logDownloads){ @@ -260,6 +260,7 @@ class DownloadWorker( finalPath = moveFile(tempFileDir.absoluteFile, downloadLocation){ progress -> setProgressAsync(workDataOf("progress" to progress)) } + setProgressAsync(workDataOf("progress" to 1000, "output" to "Moved file to $finalPath", "id" to downloadItem.id, "log" to logDownloads)) }catch (e: Exception){ finalPath = context.getString(R.string.unfound_file) e.printStackTrace() diff --git a/app/src/main/res/drawable/ic_battery.xml b/app/src/main/res/drawable/ic_battery.xml new file mode 100644 index 00000000..b8bc566e --- /dev/null +++ b/app/src/main/res/drawable/ic_battery.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/active_download_card.xml b/app/src/main/res/layout/active_download_card.xml index b23016dd..78caa092 100644 --- a/app/src/main/res/layout/active_download_card.xml +++ b/app/src/main/res/layout/active_download_card.xml @@ -47,6 +47,7 @@ android:layout_height="match_parent"> + + + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> @@ -102,5 +108,4 @@ - \ No newline at end of file diff --git a/app/src/main/res/layout/download_card.xml b/app/src/main/res/layout/download_card.xml index acf9bf2e..84e1ffe9 100644 --- a/app/src/main/res/layout/download_card.xml +++ b/app/src/main/res/layout/download_card.xml @@ -70,6 +70,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_weight="0.7" + app:layout_constraintVertical_bias="0.0" app:layout_constraintStart_toEndOf="@+id/downloads_image_view" app:layout_constraintTop_toTopOf="parent"> diff --git a/app/src/main/res/layout/fragment_history.xml b/app/src/main/res/layout/fragment_history.xml index 9751e5d3..09cb3da1 100644 --- a/app/src/main/res/layout/fragment_history.xml +++ b/app/src/main/res/layout/fragment_history.xml @@ -10,6 +10,8 @@ android:id="@+id/history_appbarlayout" app:liftOnScroll="true" android:background="@android:color/transparent" + android:elevation="0dp" + app:elevation="0dp" android:layout_width="match_parent" android:layout_height="wrap_content"> @@ -17,111 +19,111 @@ android:id="@+id/history_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - app:layout_scrollFlags="scroll|enterAlways|snap" + app:layout_scrollFlags="scroll" app:title="@string/downloads" app:menu="@menu/history_menu" android:theme="@style/Toolbar" /> - - - - - - - + - + android:visibility="gone" + android:layout_height="wrap_content"> - + app:selectionRequired="false" + app:singleSelection="false"> - + - + - + - - - + + + + + + + + + + + + + android:layout_height="wrap_content"> - - - - - - - + - + - + - + - - - + - + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de5462a2..5d6a6c6b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -189,4 +189,5 @@ End Start Automatically search for missing formats when clicking the format card + Ignore Battery Optimization \ No newline at end of file diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 2c67fa1b..cb6e080b 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -8,6 +8,11 @@ app:summary="en" app:title="@string/language" /> + + diff --git a/build.gradle b/build.gradle index 30763032..3958cb71 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { // supports java 1.6 commonsCompressVer = '1.12' youtubedlAndroidVer = "7222fe9637" - workVer = "2.8.0" + workVer = "2.8.1" composeVer = "1.4.0-alpha02" kotlinVer = "1.7.21" coroutineVer = "1.6.4"