diff --git a/app/build.gradle b/app/build.gradle index 50cb1cf4..3e9fb912 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ def properties = new Properties() def versionMajor = 1 def versionMinor = 6 def versionPatch = 6 -def versionBuild = 2 // bump for dogfood builds, public betas, etc. +def versionBuild = 3 // bump for dogfood builds, public betas, etc. def versionExt = "" if (versionBuild > 0){ 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 aa59eaad..16518b30 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/GenericDownloadAdapter.kt @@ -17,13 +17,14 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.util.FileUtil import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.squareup.picasso.Picasso -class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter(DIFF_CALLBACK) { +class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter(DIFF_CALLBACK) { private val onItemClickListener: OnItemClickListener private val activity: Activity val checkedItems: ArrayList @@ -73,7 +74,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: } val duration = card.findViewById(R.id.duration) - duration.text = item!!.duration + duration.text = item.duration // TITLE ---------------------------------- val itemTitle = card.findViewById(R.id.title) @@ -204,13 +205,13 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: } companion object { - private val DIFF_CALLBACK: DiffUtil.ItemCallback = object : DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean { + private val DIFF_CALLBACK: DiffUtil.ItemCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: DownloadItemSimple, newItem: DownloadItemSimple): Boolean { val ranged = arrayListOf(oldItem.id, newItem.id) return ranged[0] == ranged[1] } - override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean { + override fun areContentsTheSame(oldItem: DownloadItemSimple, newItem: DownloadItemSimple): Boolean { return oldItem.id == newItem.id && oldItem.title == newItem.title && oldItem.author == newItem.author && oldItem.thumb == newItem.thumb } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt index fcbcb661..eabfa80b 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/DownloadDao.kt @@ -3,6 +3,7 @@ package com.deniscerri.ytdlnis.database.dao import androidx.paging.PagingSource import androidx.room.* import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdlnis.database.models.Format import kotlinx.coroutines.flow.Flow @@ -34,7 +35,7 @@ interface DownloadDao { fun getActiveAndQueuedDownloads() : Flow> @Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id") - fun getQueuedDownloads() : PagingSource + fun getQueuedDownloads() : PagingSource @Query("SELECT format FROM downloads WHERE status='Queued' or status='QueuedPaused'") fun getSelectedFormatFromQueued() : List @@ -49,7 +50,7 @@ interface DownloadDao { fun getQueuedDownloadsList() : List @Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC") - fun getCancelledDownloads() : PagingSource + fun getCancelledDownloads() : PagingSource @Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC") fun getCancelledDownloadsList() : List @@ -58,13 +59,13 @@ interface DownloadDao { fun getPausedDownloadsList() : List @Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC") - fun getErroredDownloads() : PagingSource + fun getErroredDownloads() : PagingSource @Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC") fun getErroredDownloadsList() : List @Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC") - fun getSavedDownloads() : PagingSource + fun getSavedDownloads() : PagingSource @Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC") fun getSavedDownloadsList() : List @@ -115,6 +116,9 @@ interface DownloadDao { @Query("DELETE FROM downloads WHERE status='Saved'") suspend fun deleteSaved() + @Query("DELETE FROM downloads WHERE id in (:list)") + suspend fun deleteAllWithIDs(list: List) + @Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued' or status='QueuedPaused'") suspend fun cancelQueued() diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItemSimple.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItemSimple.kt new file mode 100644 index 00000000..638b3d4f --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItemSimple.kt @@ -0,0 +1,21 @@ +package com.deniscerri.ytdlnis.database.models + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel + +@Entity(tableName = "downloads") +data class DownloadItemSimple( + @PrimaryKey(autoGenerate = true) + var id: Long, + var url: String, + var title: String, + var author: String, + var thumb: String, + var duration: String, + var format: Format, + @ColumnInfo(defaultValue = "Queued") + var status: String, + var logID: Long? +) \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt index e32cce30..1a536f01 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/DownloadRepository.kt @@ -5,6 +5,7 @@ import androidx.paging.PagingConfig import com.deniscerri.ytdlnis.App import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdlnis.util.FileUtil import kotlinx.coroutines.flow.Flow import java.io.File @@ -16,19 +17,19 @@ class DownloadRepository(private val downloadDao: DownloadDao) { pagingSourceFactory = {downloadDao.getAllDownloads()} ) val activeDownloads : Flow> = downloadDao.getActiveDownloads() - val queuedDownloads : Pager = Pager( + val queuedDownloads : Pager = Pager( config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1), pagingSourceFactory = {downloadDao.getQueuedDownloads()} ) - val cancelledDownloads : Pager = Pager( + val cancelledDownloads : Pager = Pager( config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1), pagingSourceFactory = {downloadDao.getCancelledDownloads()} ) - val erroredDownloads : Pager = Pager( + val erroredDownloads : Pager = Pager( config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1), pagingSourceFactory = {downloadDao.getErroredDownloads()} ) - val savedDownloads : Pager = Pager( + val savedDownloads : Pager = Pager( config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1), pagingSourceFactory = {downloadDao.getSavedDownloads()} ) @@ -114,6 +115,11 @@ class DownloadRepository(private val downloadDao: DownloadDao) { downloadDao.deleteSaved() } + suspend fun deleteAllWithIDs(ids: List){ + downloadDao.deleteAllWithIDs(ids) + + } + suspend fun cancelQueued(){ downloadDao.cancelQueued() } 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 8deab4ea..08f69d59 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 @@ -8,6 +8,7 @@ import android.content.res.Resources import android.net.ConnectivityManager import android.os.Looper import android.util.DisplayMetrics +import android.util.Log import android.widget.Toast import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData @@ -31,6 +32,7 @@ import com.deniscerri.ytdlnis.database.dao.ResultDao import com.deniscerri.ytdlnis.database.models.AudioPreferences import com.deniscerri.ytdlnis.database.models.CommandTemplate import com.deniscerri.ytdlnis.database.models.DownloadItem +import com.deniscerri.ytdlnis.database.models.DownloadItemSimple import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdlnis.database.models.HistoryItem import com.deniscerri.ytdlnis.database.models.ResultItem @@ -62,12 +64,12 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application private val commandTemplateDao: CommandTemplateDao private val infoUtil : InfoUtil val allDownloads : Flow> - val queuedDownloads : Flow> + val queuedDownloads : Flow> val activeDownloads : LiveData> val activeDownloadsCount : LiveData - val cancelledDownloads : Flow> - val erroredDownloads : Flow> - val savedDownloads : Flow> + val cancelledDownloads : Flow> + val erroredDownloads : Flow> + val savedDownloads : Flow> private var bestVideoFormat : Format private var bestAudioFormat : Format @@ -125,35 +127,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application resources = Resources(application.assets, metrics, confTmp) - val videoFormatValues = resources.getStringArray(R.array.video_formats_values) videoContainer = sharedPreferences.getString("video_format", "Default") - - defaultVideoFormats = mutableListOf() - videoFormatValues.forEach { - val tmp = Format( - it, - videoContainer!!, - "", - "", - "", - 0, - it - ) - defaultVideoFormats.add(tmp) - } - formatIDPreference.reversed().forEach { - val tmp = Format( - it, - videoContainer!!, - "", - "", - "", - 0, - it - ) - defaultVideoFormats.add(tmp) - } - + defaultVideoFormats = getGenericVideoFormats() bestVideoFormat = defaultVideoFormats.last() audioContainer = sharedPreferences.getString("audio_format", "mp3") @@ -200,11 +175,17 @@ 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 + fun getDownloadType(t: Type, url: String) : Type { + return when(t){ + Type.auto -> { + if (urlsForAudioType.any { url.contains(it) }){ + Type.audio + }else{ + Type.video + } + } + else -> t } - return Type.video } fun createDownloadItemFromResult(resultItem: ResultItem, givenType: Type) : DownloadItem { @@ -214,10 +195,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false) val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false) - var type = givenType - if (type == Type.auto){ - type = getSuitableDownloadType(resultItem.url) - } + var type = getDownloadType(givenType, resultItem.url) if(type == Type.command && commandTemplateDao.getTotalNumber() == 0) type = Type.video val customFileNameTemplate = when(type) { @@ -466,8 +444,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val audioFormats = resources.getStringArray(R.array.audio_formats) val formats = mutableListOf() val containerPreference = sharedPreferences.getString("audio_format", "") - audioFormatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) } audioFormats.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) } + audioFormatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"","", "",1, it)) } return formats } @@ -475,8 +453,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val videoFormats = resources.getStringArray(R.array.video_formats_values) val formats = mutableListOf() val containerPreference = sharedPreferences.getString("video_format", "") - formatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",0, it)) } videoFormats.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",0, it)) } + formatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",1, it)) } return formats } @@ -489,8 +467,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application val list : MutableList = mutableListOf() 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!!))) + preferredType = getDownloadType(Type.valueOf(preferredType!!), it!!.url).toString() + list.add(createDownloadItemFromResult(it, Type.valueOf(preferredType!!))) } return list } @@ -525,6 +503,11 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application repository.deleteSaved() } + fun deleteAllWithID(ids: List) = viewModelScope.launch(Dispatchers.IO){ + Log.e("Aa", ids.size.toString()) + repository.deleteAllWithIDs(ids) + } + fun cancelQueued() = viewModelScope.launch(Dispatchers.IO) { repository.cancelQueued() } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt index ebb809dc..aae9bdf3 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/receiver/ShareActivity.kt @@ -164,7 +164,7 @@ class ShareActivity : BaseActivity() { private fun showDownloadSheet(it: ResultItem){ if (sharedPreferences.getBoolean("download_card", true)){ - val bottomSheet = DownloadBottomSheetDialog(it, DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!), null, quickDownload) + val bottomSheet = DownloadBottomSheetDialog(it,downloadViewModel.getDownloadType(DownloadViewModel.Type.valueOf(sharedPreferences.getString("preferred_download_type", "video")!!), it.url), null, quickDownload) bottomSheet.show(supportFragmentManager, "downloadSingleSheet") }else{ lifecycleScope.launch(Dispatchers.IO){ 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 cfe0b4fa..c52b11cf 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -23,6 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.children import androidx.core.view.forEach +import androidx.core.view.forEachIndexed import androidx.core.view.isVisible import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.Fragment @@ -283,7 +284,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene val providersChipGroup = searchView!!.findViewById(R.id.providers) val providers = resources.getStringArray(R.array.search_engines) val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList() - val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch") for(i in providersValues.indices){ val provider = providers[i] @@ -291,8 +291,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene val tmp = layoutinflater!!.inflate(R.layout.filter_chip, providersChipGroup, false) as Chip tmp.text = provider tmp.id = i - - if (currentProvider == providerValue) tmp.isChecked = true + tmp.tag = providersValues[i] tmp.setOnClickListener { val editor = sharedPreferences?.edit() @@ -308,6 +307,15 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene infoUtil = InfoUtil(requireContext()) searchView!!.addTransitionListener { _, _, newState -> if (newState == SearchView.TransitionState.SHOWN) { + val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch") + providersChipGroup.children.forEach { + val tmp = providersChipGroup.findViewById(it.id) + if (tmp.tag == currentProvider) { + tmp.isChecked = true + return@forEach + } + } + try{ val clipboard = requireContext().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager @@ -596,7 +604,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene } private fun showSingleDownloadSheet(resultItem : ResultItem, type: DownloadViewModel.Type, quickDownload: Boolean){ - val bottomSheet = DownloadBottomSheetDialog(resultItem, type, null, quickDownload) + val bottomSheet = DownloadBottomSheetDialog(resultItem, downloadViewModel.getDownloadType(type, resultItem.url), null, quickDownload) bottomSheet.show(parentFragmentManager, "downloadSingleSheet") } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/AddExtraCommandsDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/AddExtraCommandsDialog.kt index 08f2e02a..fbcce7b7 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/AddExtraCommandsDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/AddExtraCommandsDialog.kt @@ -127,8 +127,10 @@ class AddExtraCommandsDialog(private val item: DownloadItem?, private val callba Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show() }else{ lifecycleScope.launch { - UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){ template -> - text.text.insert(text.selectionStart, "${template.content} ") + UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){ templates -> + templates.forEach { + text.text.insert(text.selectionStart, "${it.content} ") + } text.postDelayed({ text.requestFocus() imm.showSoftInput(text, 0) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt index 28f90922..94058679 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadCommandFragment.kt @@ -132,16 +132,19 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu commandTemplateCard.setOnClickListener { lifecycleScope.launch { UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){ - chosenCommandView.editText!!.setText(it.content) - populateCommandCard(commandTemplateCard, it) + chosenCommandView.editText!!.text.clear() + it.forEach { c -> + chosenCommandView.editText!!.text.insert(chosenCommandView.editText!!.selectionStart, "${c.content} ") + } + populateCommandCard(commandTemplateCard, it.first()) downloadItem.format = Format( - it.title, + it.first().title, "", "", "", "", 0, - it.content + it.map { c -> c.content }.joinToString { " " } ) } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt index 59de8e05..1a948230 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloadcard/DownloadMultipleBottomSheetDialog.kt @@ -12,6 +12,7 @@ import android.graphics.Color import android.os.Bundle import android.text.format.DateFormat import android.util.DisplayMetrics +import android.util.Log import android.view.Gravity import android.view.LayoutInflater import android.view.MenuItem @@ -328,7 +329,16 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList c.content } + ) + items.forEach { f -> f.format = format } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt index b51d2f89..7587f8ae 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/CancelledDownloadsFragment.kt @@ -202,9 +202,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic } adapter.clearCheckedItems() - for (id in selectedObjects){ - downloadViewModel.deleteDownload(id) - } + downloadViewModel.deleteAllWithID(selectedObjects) actionMode?.finish() } } 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 9068aa8e..12cb091f 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 @@ -208,9 +208,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL adapter.checkedItems.toList() } adapter.clearCheckedItems() - for (id in selectedObjects){ - downloadViewModel.deleteDownload(id) - } + downloadViewModel.deleteAllWithID(selectedObjects) actionMode?.finish() } } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt index 85c7a64e..2ca78f45 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/QueuedDownloadsFragment.kt @@ -260,8 +260,8 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi YoutubeDL.getInstance().destroyProcessById(id.toInt().toString()) WorkManager.getInstance(requireContext()).cancelAllWorkByTag(id.toInt().toString()) notificationUtil.cancelDownloadNotification(id.toInt()) - downloadViewModel.deleteDownload(id) } + downloadViewModel.deleteAllWithID(selectedObjects) actionMode?.finish() } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt index 259f2507..a4df73d0 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/downloads/SavedDownloadsFragment.kt @@ -222,9 +222,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis adapter.checkedItems.toList() } adapter.clearCheckedItems() - withContext(Dispatchers.IO) { - downloadViewModel.reQueueDownloadItems(selectedObjects) - } + downloadViewModel.deleteAllWithID(selectedObjects) actionMode?.finish() } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/TerminalActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/TerminalActivity.kt index 0ca74e42..06b75552 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/TerminalActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/TerminalActivity.kt @@ -1,5 +1,6 @@ package com.deniscerri.ytdlnis.ui.more +import android.app.ActionBar.LayoutParams import android.app.Activity import android.content.ClipboardManager import android.content.Context @@ -8,8 +9,8 @@ import android.content.SharedPreferences import android.net.Uri import android.os.Build import android.os.Bundle -import android.os.FileObserver import android.os.PersistableBundle +import android.util.DisplayMetrics import android.util.Log import android.view.MenuItem import android.view.View @@ -22,7 +23,6 @@ import android.widget.ScrollView import android.widget.TextView import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts -import androidx.core.view.forEach import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.preference.PreferenceManager @@ -62,8 +62,8 @@ class TerminalActivity : BaseActivity() { private lateinit var sharedPreferences: SharedPreferences private var downloadID by Delegates.notNull() private lateinit var downloadFile : File - private lateinit var observer: FileObserver private lateinit var imm : InputMethodManager + private lateinit var metrics: DisplayMetrics var context: Context? = null public override fun onCreate(savedInstanceState: Bundle?) { @@ -82,6 +82,8 @@ class TerminalActivity : BaseActivity() { commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java] sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) + metrics = DisplayMetrics() + windowManager.defaultDisplay.getMetrics(metrics) bottomAppBar = findViewById(R.id.bottomAppBar) @@ -113,8 +115,10 @@ class TerminalActivity : BaseActivity() { Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show() }else{ lifecycleScope.launch { - UiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template -> - input!!.text.insert(input!!.selectionStart, template.content + " ") + UiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ templates -> + templates.forEach {c -> + input!!.text.insert(input!!.selectionStart, c.content + " ") + } input!!.postDelayed({ input!!.requestFocus() imm.showSoftInput(input!!, 0) @@ -146,7 +150,7 @@ class TerminalActivity : BaseActivity() { output = findViewById(R.id.custom_command_output) output!!.setTextIsSelectable(true) - output!!.setHorizontallyScrolling(true) + output!!.layoutParams!!.width = LayoutParams.WRAP_CONTENT input = findViewById(R.id.command_edittext) input!!.requestFocus() fab = findViewById(R.id.command_fab) @@ -168,38 +172,6 @@ class TerminalActivity : BaseActivity() { notificationUtil = NotificationUtil(this) handleIntent(intent) - if(Build.VERSION.SDK_INT < 29){ - observer = object : FileObserver(downloadFile.absolutePath, MODIFY) { - override fun onEvent(event: Int, p: String?) { - runOnUiThread{ - try { - val newText = downloadFile.readText() - if (newText.isBlank()) return@runOnUiThread - output!!.append(newText) - output!!.scrollTo(0, output!!.height) - scrollView!!.fullScroll(View.FOCUS_DOWN) - }catch (ignored: Exception) {} - } - } - } - observer.startWatching() - }else{ - observer = object : FileObserver(downloadFile, MODIFY) { - override fun onEvent(event: Int, p: String?) { - runOnUiThread{ - try { - val newText = downloadFile.readText() - if (newText.isBlank()) return@runOnUiThread - output!!.append(newText) - output!!.scrollTo(0, output!!.height) - scrollView!!.fullScroll(View.FOCUS_DOWN) - }catch (ignored: Exception) {} - } - } - } - observer.startWatching() - } - WorkManager.getInstance(this) .getWorkInfosForUniqueWorkLiveData(downloadID.toString()) .observe(this){ list -> @@ -269,7 +241,6 @@ class TerminalActivity : BaseActivity() { scrollView.id = R.id.horizontalscroll_output parent.addView(scrollView, 0) } - output?.setHorizontallyScrolling(output?.canScrollHorizontally(1) != true) } R.id.export_clipboard -> { lifecycleScope.launch(Dispatchers.IO){ @@ -317,12 +288,10 @@ class TerminalActivity : BaseActivity() { private fun hideCancelFab() { fab!!.text = getString(R.string.run_command) fab!!.setIconResource(R.drawable.ic_baseline_keyboard_arrow_right_24) - topAppBar!!.menu.forEach { it.isEnabled = true } } private fun showCancelFab() { fab!!.text = getString(R.string.cancel_download) fab!!.setIconResource(R.drawable.ic_cancel) - topAppBar!!.menu.forEach { it.isEnabled = false } } private var commandPathResultLauncher = registerForActivityResult( diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt index 999a459c..518e1fd2 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/more/settings/GeneralSettingsFragment.kt @@ -29,6 +29,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() { override val title: Int = R.string.general private var language: ListPreference? = null + private var language13: Preference? = null private var theme: ListPreference? = null private var accent: ListPreference? = null private var highContrast: SwitchPreferenceCompat? = null @@ -50,6 +51,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() { } language = findPreference("app_language") + language13 = findPreference("app_language_13") theme = findPreference("ytdlnis_theme") accent = findPreference("theme_accent") highContrast = findPreference("high_contrast") @@ -63,18 +65,32 @@ class GeneralSettingsFragment : BaseSettingsFragment() { entries.add(Locale(it).getDisplayName(Locale(it))) } language!!.entries = entries.toTypedArray() - }else{ - language!!.isVisible = false - } - if(language!!.value == null) language!!.value = Locale.getDefault().language - language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value)) - language!!.onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> - language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString())) - AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString())) + if(language!!.value == null) language!!.value = Locale.getDefault().language + language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value)) + + language!!.onPreferenceChangeListener = + Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any -> + language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString())) + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString())) + true + } + + language13?.isVisible = false + }else{ + language?.isVisible = false + language13?.isVisible = true + language13?.summary = Locale.getDefault().displayLanguage + + language13!!.setOnPreferenceClickListener { + val intent = Intent(Settings.ACTION_APP_LOCALE_SETTINGS) + intent.data = Uri.fromParts("package", requireActivity().packageName, null) + requireActivity().startActivity(intent) + requireActivity().finishAffinity() true } + } + theme!!.summary = theme!!.entry theme!!.onPreferenceChangeListener = 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 41a9274d..b0815c6c 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 @@ -245,7 +245,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() historyItems.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -259,7 +259,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -273,7 +273,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -287,7 +287,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -301,7 +301,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -315,7 +315,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -330,7 +330,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { val arr = JsonArray() items.forEach { it.useAsExtraCommand = false - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -344,7 +344,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() items.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -358,7 +358,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() { } val arr = JsonArray() historyItems.forEach { - arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject) + arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject) } return arr } @@ -380,7 +380,6 @@ class MainSettingsFragment : PreferenceFragmentCompat() { lifecycleScope.launch { val preferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) - val editor = preferences.edit() runCatching { val ip = requireContext().contentResolver.openInputStream(result.data!!.data!!) 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 55d4ad4a..c8fb3a4d 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/FileUtil.kt @@ -290,7 +290,7 @@ object FileUtil { } fun convertFileSize(s: Long): String{ - if (s <= 0) return "?" + if (s <= 1) return "?" val units = arrayOf("B", "kB", "MB", "GB", "TB") val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt() val symbols = DecimalFormatSymbols(Locale.US) 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 2a3075f6..3f3ccff0 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt @@ -5,6 +5,7 @@ import android.content.SharedPreferences import android.os.Looper import android.text.Html import android.util.Log +import android.util.Patterns import android.widget.Toast import androidx.preference.PreferenceManager import com.deniscerri.ytdlnis.R @@ -547,7 +548,6 @@ class InfoUtil(private val context: Context) { fun getFromYTDL(query: String): ArrayList { items = ArrayList() - val webpage_urls = mutableListOf() val searchEngine = sharedPreferences.getString("search_engine", "ytsearch") try { val request : YoutubeDLRequest @@ -656,7 +656,11 @@ class InfoUtil(private val context: Context) { val url = if (jsonObject.has("url")){ jsonObject.getString("url") }else{ - jsonObject.getString("webpage_url") + if (Patterns.WEB_URL.matcher(query).matches()){ + query + }else{ + jsonObject.getString("webpage_url") + } } items.add(ResultItem(0, @@ -672,10 +676,6 @@ class InfoUtil(private val context: Context) { chapters ) ) - webpage_urls.add(jsonObject.getString("webpage_url")) - } - if (items.size == 1){ - items[0]?.url = webpage_urls.first() } } catch (e: Exception) { Looper.prepare().run { @@ -970,20 +970,6 @@ class InfoUtil(private val context: Context) { downDir.mkdirs() } - if (downloadItem.playlistTitle.isNotBlank()){ - request.addOption("--parse-metadata","${downloadItem.playlistTitle.split("[")[0]}:%(playlist)s") - runCatching { - request.addOption("--parse-metadata", - downloadItem.playlistTitle - .substring( - downloadItem.playlistTitle.indexOf("[") + 1, - downloadItem.playlistTitle.indexOf("]"), - ) + ":%(playlist_index)s" - ) - } - } - - val aria2 = sharedPreferences.getBoolean("aria2", false) if (aria2) { request.addOption("--downloader", "libaria2c.so") @@ -1001,6 +987,7 @@ class InfoUtil(private val context: Context) { val limitRate = sharedPreferences.getString("limit_rate", "") if (limitRate != "") request.addOption("-r", limitRate!!) + request.addOption("--trim-filenames", 120) if(downloadItem.type != DownloadViewModel.Type.command){ if (downloadItem.SaveThumb) { request.addOption("--write-thumbnail") @@ -1034,12 +1021,12 @@ class InfoUtil(private val context: Context) { } if(downloadItem.title.isNotBlank()){ - request.addOption("--parse-metadata", downloadItem.title.take(200) + ":%(title)s") + request.addCommands(listOf("--replace-in-metadata", "title", ".+", downloadItem.title)) } if (downloadItem.author.isNotBlank()){ - request.addOption("--parse-metadata", downloadItem.author.take(25) + ":%(artist)s") + request.addCommands(listOf("--replace-in-metadata", "uploader", ".+", downloadItem.author)) + request.addCommands(listOf("--replace-in-metadata","uploader"," - Topic$","")) } - request.addCommands(listOf("--replace-in-metadata","artist"," - Topic$","")) if (downloadItem.downloadSections.isNotBlank()){ downloadItem.downloadSections.split(";").forEach { @@ -1077,6 +1064,21 @@ class InfoUtil(private val context: Context) { if (sharedPreferences.getBoolean("write_description", false)){ request.addOption("--write-description") } + + if (downloadItem.playlistTitle.isNotBlank()){ + request.addOption("--parse-metadata","${downloadItem.playlistTitle.split("[")[0]}:%(playlist)s") + runCatching { + request.addOption("--parse-metadata", + downloadItem.playlistTitle + .substring( + downloadItem.playlistTitle.indexOf("[") + 1, + downloadItem.playlistTitle.indexOf("]"), + ) + ":%(playlist_index)s" + ) + } + } + + } if (sharedPreferences.getBoolean("restrict_filenames", true)) { @@ -1144,7 +1146,7 @@ class InfoUtil(private val context: Context) { if (! request.hasOption("--convert-thumbnails")) request.addOption("--convert-thumbnails", "jpg") if (sharedPreferences.getBoolean("crop_thumbnail", true)){ try { - val config = File(context.cacheDir.absolutePath + "/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt") + val config = File(context.cacheDir.absolutePath + "/config" + downloadItem.id + "##ffmpegCrop.txt") val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\"" config.writeText(configData) request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1") @@ -1156,7 +1158,7 @@ class InfoUtil(private val context: Context) { } if (downloadItem.customFileNameTemplate.isNotBlank()){ - request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s") + request.addOption("-o", "${downloadItem.customFileNameTemplate.removeSuffix(".%(ext)s")}.%(ext)s") } } @@ -1318,7 +1320,7 @@ class InfoUtil(private val context: Context) { request.addOption("-o", "chapter:%(section_title)s.%(ext)s") }else{ if (downloadItem.customFileNameTemplate.isNotBlank()){ - request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s") + request.addOption("-o", "${downloadItem.customFileNameTemplate.removeSuffix(".%(ext)s")}.%(ext)s") } } @@ -1351,10 +1353,16 @@ class InfoUtil(private val context: Context) { var final = java.lang.String.join(" ", arr).replace("\"\"", "\" \"") val ppas = "--config(-locations)? \"(.*?)\"".toRegex().findAll(final) - ppas.forEach { - val path = "\"(.*?)\"".toRegex().find(it.value)?.value?.replace("\"", "") - final = final.replace(it.value, "") - final += " ${File(path ?: "").readText()}" + ppas.forEach {res -> + val path = "\"(.*?)\"".toRegex().find(res.value)?.value?.replace("\"", "") + val newVal = runCatching { + File(path ?: "").readText() + }.onFailure { + res.value + }.getOrDefault("") + + final = final.replace(res.value, newVal) + } return final diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt index d0bfbdd0..556d9212 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/UiUtil.kt @@ -31,6 +31,7 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.core.view.isVisible @@ -543,14 +544,14 @@ object UiUtil { bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE) bottomSheet.setContentView(R.layout.format_details_sheet) - val formatIdParent = bottomSheet.findViewById(R.id.format_id_parent) - val formatURLParent = bottomSheet.findViewById(R.id.format_url_parent) - val containerParent = bottomSheet.findViewById(R.id.container_parent) - val codecParent = bottomSheet.findViewById(R.id.codec_parent) - val filesizeParent = bottomSheet.findViewById(R.id.filesize_parent) - val formatnoteParent = bottomSheet.findViewById(R.id.format_note_parent) - val fpsParent = bottomSheet.findViewById(R.id.fps_parent) - val asrParent = bottomSheet.findViewById(R.id.asr_parent) + val formatIdParent = bottomSheet.findViewById(R.id.format_id_parent) + val formatURLParent = bottomSheet.findViewById(R.id.format_url_parent) + val containerParent = bottomSheet.findViewById(R.id.container_parent) + val codecParent = bottomSheet.findViewById(R.id.codec_parent) + val filesizeParent = bottomSheet.findViewById(R.id.filesize_parent) + val formatnoteParent = bottomSheet.findViewById(R.id.format_note_parent) + val fpsParent = bottomSheet.findViewById(R.id.fps_parent) + val asrParent = bottomSheet.findViewById(R.id.asr_parent) if (format.format_id.isBlank()) formatIdParent?.visibility = View.GONE else { @@ -690,7 +691,7 @@ object UiUtil { } - suspend fun showCommandTemplates(activity: Activity, commandTemplateViewModel: CommandTemplateViewModel, itemSelected: (itemSelected: CommandTemplate) -> Unit) { + suspend fun showCommandTemplates(activity: Activity, commandTemplateViewModel: CommandTemplateViewModel, itemSelected: (itemSelected: List) -> Unit) { val bottomSheet = BottomSheetDialog(activity) bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE) bottomSheet.setContentView(R.layout.command_template_list) @@ -701,17 +702,33 @@ object UiUtil { } linearLayout!!.removeAllViews() + val selectedItems = mutableListOf() + val ok = bottomSheet.findViewById(R.id.command_ok) + ok?.isEnabled = list.size == 1 + list.forEach {template -> val item = activity.layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as MaterialCardView item.findViewById(R.id.title).text = template.title item.findViewById(R.id.content).text = template.content item.setOnClickListener { - itemSelected(template) - bottomSheet.cancel() + if (selectedItems.contains(template)){ + selectedItems.remove(template) + (it as MaterialCardView).isChecked = false + }else{ + selectedItems.add(template) + (it as MaterialCardView).isChecked = true + } + + ok?.isEnabled = selectedItems.isNotEmpty() } linearLayout.addView(item) } + ok?.setOnClickListener { + itemSelected(selectedItems.ifEmpty { listOf(list.first()) }) + bottomSheet.cancel() + } + bottomSheet.show() bottomSheet.window!!.setLayout( ViewGroup.LayoutParams.MATCH_PARENT, @@ -913,9 +930,6 @@ object UiUtil { ) { _: DialogInterface?, _: Int -> } val dialog = builder.create() - editText.doOnTextChanged { _, _, _, _ -> - dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty() - } dialog.show() val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager editText!!.postDelayed({ @@ -1016,9 +1030,6 @@ object UiUtil { ) { _: DialogInterface?, _: Int -> } val dialog = builder.create() - editText.doOnTextChanged { _, _, _, _ -> - dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty() - } dialog.show() val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager editText!!.postDelayed({ 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 ba34dd2b..4b33d3fc 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/DownloadWorker.kt @@ -116,11 +116,7 @@ class DownloadWorker( "Title: ${downloadItem.title}\n" + "URL: ${downloadItem.url}\n" + "Type: ${downloadItem.type}\n" + - if (downloadItem.type != DownloadViewModel.Type.command){ - "Format: ${downloadItem.format}\n\n" - } - else { "" } + - "Command:\n ${infoUtil.parseYTDLRequestString(request)} ${downloadItem.extraCommands}\n\n", + "Command:\n ${infoUtil.parseYTDLRequestString(request)}\n\n", downloadItem.format, downloadItem.type, System.currentTimeMillis(), diff --git a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt index 8b8170bd..f128204f 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/work/TerminalDownloadWorker.kt @@ -100,7 +100,13 @@ class TerminalDownloadWorker( } YoutubeDL.getInstance().execute(request, itemId.toString()){ progress, _, line -> - setProgressAsync(workDataOf("progress" to progress.toInt(), "output" to line.chunked(5000).first().toString(), "id" to itemId, "log" to logDownloads)) + runBlocking { + line.chunked(10000).forEach { + setProgress(workDataOf("progress" to progress.toInt(), "output" to it, "id" to itemId, "log" to logDownloads)) + Thread.sleep(100) + } + } + val title: String = command.take(65) notificationUtil.updateDownloadNotification( itemId, @@ -128,32 +134,46 @@ class TerminalDownloadWorker( } } - outputFile.appendText("${it.out}\n") - if (logDownloads){ - CoroutineScope(Dispatchers.IO).launch { - logRepo.update(it.out, logItem.id) + return runBlocking { + it.out.chunked(10000).forEach { + setProgress(workDataOf("progress" to 100, "output" to it, "id" to itemId, "log" to logDownloads)) + Thread.sleep(100) } - } - notificationUtil.cancelDownloadNotification(itemId) + if (logDownloads){ + CoroutineScope(Dispatchers.IO).launch { + logRepo.update(it.out, logItem.id) + } + } + notificationUtil.cancelDownloadNotification(itemId) + return@runBlocking Result.success() + } }.onFailure { if (it is YoutubeDL.CanceledException) { return Result.failure() } - outputFile.appendText("\n${it.message}\n") - if (logDownloads){ - CoroutineScope(Dispatchers.IO).launch { - if (it.message != null){ - logRepo.update(it.message!!, logItem.id) + + return runBlocking { + it.message?.chunked(10000)?.forEach { + setProgress(workDataOf("progress" to 100, "output" to it, "id" to itemId, "log" to logDownloads)) + Thread.sleep(100) + } + + if (logDownloads){ + CoroutineScope(Dispatchers.IO).launch { + if (it.message != null){ + logRepo.update(it.message!!, logItem.id) + } } } + File(FileUtil.getDefaultCommandPath() + "/" + itemId).deleteRecursively() + Log.e(TAG, context.getString(R.string.failed_download), it) + notificationUtil.cancelDownloadNotification(itemId) + + return@runBlocking Result.failure() } - File(FileUtil.getDefaultCommandPath() + "/" + itemId).deleteRecursively() - Log.e(TAG, context.getString(R.string.failed_download), it) - notificationUtil.cancelDownloadNotification(itemId) - return Result.failure() } return Result.success() diff --git a/app/src/main/res/layout/command_template_list.xml b/app/src/main/res/layout/command_template_list.xml index 6e54e834..022d0c8b 100644 --- a/app/src/main/res/layout/command_template_list.xml +++ b/app/src/main/res/layout/command_template_list.xml @@ -24,8 +24,12 @@ android:id="@+id/bottom_sheet_title" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:singleLine="false" android:text="@string/command_templates" android:textSize="25sp" + android:maxLines="2" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintEnd_toStartOf="@+id/command_ok" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -39,6 +43,18 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" /> +