stuff
Fix format details fps in arabic being rtl Removed h264 from codec Fixed Search engine not getting updated in home when changing in settings fragment. Added language preference in android 13 and up Added multiple selection for command templates Fix issue when app crashes when creating config files for items with weird titles Fix auto preferred download type not working correctly in yt music
This commit is contained in:
parent
25f53aeb87
commit
2d08d2f643
30 changed files with 422 additions and 304 deletions
|
|
@ -10,7 +10,7 @@ def properties = new Properties()
|
||||||
def versionMajor = 1
|
def versionMajor = 1
|
||||||
def versionMinor = 6
|
def versionMinor = 6
|
||||||
def versionPatch = 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 = ""
|
def versionExt = ""
|
||||||
|
|
||||||
if (versionBuild > 0){
|
if (versionBuild > 0){
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,14 @@ import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
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.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter<DownloadItem, GenericDownloadAdapter.ViewHolder>(DIFF_CALLBACK) {
|
class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : PagingDataAdapter<DownloadItemSimple, GenericDownloadAdapter.ViewHolder>(DIFF_CALLBACK) {
|
||||||
private val onItemClickListener: OnItemClickListener
|
private val onItemClickListener: OnItemClickListener
|
||||||
private val activity: Activity
|
private val activity: Activity
|
||||||
val checkedItems: ArrayList<Long>
|
val checkedItems: ArrayList<Long>
|
||||||
|
|
@ -73,7 +74,7 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
val duration = card.findViewById<TextView>(R.id.duration)
|
val duration = card.findViewById<TextView>(R.id.duration)
|
||||||
duration.text = item!!.duration
|
duration.text = item.duration
|
||||||
|
|
||||||
// TITLE ----------------------------------
|
// TITLE ----------------------------------
|
||||||
val itemTitle = card.findViewById<TextView>(R.id.title)
|
val itemTitle = card.findViewById<TextView>(R.id.title)
|
||||||
|
|
@ -204,13 +205,13 @@ class GenericDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItemSimple> = object : DiffUtil.ItemCallback<DownloadItemSimple>() {
|
||||||
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
override fun areItemsTheSame(oldItem: DownloadItemSimple, newItem: DownloadItemSimple): Boolean {
|
||||||
val ranged = arrayListOf(oldItem.id, newItem.id)
|
val ranged = arrayListOf(oldItem.id, newItem.id)
|
||||||
return ranged[0] == ranged[1]
|
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
|
return oldItem.id == newItem.id && oldItem.title == newItem.title && oldItem.author == newItem.author && oldItem.thumb == newItem.thumb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.deniscerri.ytdlnis.database.dao
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
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.Format
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ interface DownloadDao {
|
||||||
fun getActiveAndQueuedDownloads() : Flow<List<DownloadItem>>
|
fun getActiveAndQueuedDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status='Queued' or status='QueuedPaused' ORDER BY downloadStartTime, id")
|
||||||
fun getQueuedDownloads() : PagingSource<Int, DownloadItem>
|
fun getQueuedDownloads() : PagingSource<Int, DownloadItemSimple>
|
||||||
|
|
||||||
@Query("SELECT format FROM downloads WHERE status='Queued' or status='QueuedPaused'")
|
@Query("SELECT format FROM downloads WHERE status='Queued' or status='QueuedPaused'")
|
||||||
fun getSelectedFormatFromQueued() : List<Format>
|
fun getSelectedFormatFromQueued() : List<Format>
|
||||||
|
|
@ -49,7 +50,7 @@ interface DownloadDao {
|
||||||
fun getQueuedDownloadsList() : List<DownloadItem>
|
fun getQueuedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
||||||
fun getCancelledDownloads() : PagingSource<Int, DownloadItem>
|
fun getCancelledDownloads() : PagingSource<Int, DownloadItemSimple>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
|
||||||
fun getCancelledDownloadsList() : List<DownloadItem>
|
fun getCancelledDownloadsList() : List<DownloadItem>
|
||||||
|
|
@ -58,13 +59,13 @@ interface DownloadDao {
|
||||||
fun getPausedDownloadsList() : List<DownloadItem>
|
fun getPausedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
|
||||||
fun getErroredDownloads() : PagingSource<Int, DownloadItem>
|
fun getErroredDownloads() : PagingSource<Int, DownloadItemSimple>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
|
||||||
fun getErroredDownloadsList() : List<DownloadItem>
|
fun getErroredDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC")
|
||||||
fun getSavedDownloads() : PagingSource<Int, DownloadItem>
|
fun getSavedDownloads() : PagingSource<Int, DownloadItemSimple>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC")
|
@Query("SELECT * FROM downloads WHERE status='Saved' ORDER BY id DESC")
|
||||||
fun getSavedDownloadsList() : List<DownloadItem>
|
fun getSavedDownloadsList() : List<DownloadItem>
|
||||||
|
|
@ -115,6 +116,9 @@ interface DownloadDao {
|
||||||
@Query("DELETE FROM downloads WHERE status='Saved'")
|
@Query("DELETE FROM downloads WHERE status='Saved'")
|
||||||
suspend fun deleteSaved()
|
suspend fun deleteSaved()
|
||||||
|
|
||||||
|
@Query("DELETE FROM downloads WHERE id in (:list)")
|
||||||
|
suspend fun deleteAllWithIDs(list: List<Long>)
|
||||||
|
|
||||||
@Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued' or status='QueuedPaused'")
|
@Query("UPDATE downloads SET status='Cancelled' WHERE status='Queued' or status='QueuedPaused'")
|
||||||
suspend fun cancelQueued()
|
suspend fun cancelQueued()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
|
)
|
||||||
|
|
@ -5,6 +5,7 @@ import androidx.paging.PagingConfig
|
||||||
import com.deniscerri.ytdlnis.App
|
import com.deniscerri.ytdlnis.App
|
||||||
import com.deniscerri.ytdlnis.database.dao.DownloadDao
|
import com.deniscerri.ytdlnis.database.dao.DownloadDao
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItemSimple
|
||||||
import com.deniscerri.ytdlnis.util.FileUtil
|
import com.deniscerri.ytdlnis.util.FileUtil
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
@ -16,19 +17,19 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
pagingSourceFactory = {downloadDao.getAllDownloads()}
|
pagingSourceFactory = {downloadDao.getAllDownloads()}
|
||||||
)
|
)
|
||||||
val activeDownloads : Flow<List<DownloadItem>> = downloadDao.getActiveDownloads()
|
val activeDownloads : Flow<List<DownloadItem>> = downloadDao.getActiveDownloads()
|
||||||
val queuedDownloads : Pager<Int, DownloadItem> = Pager(
|
val queuedDownloads : Pager<Int, DownloadItemSimple> = Pager(
|
||||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||||
pagingSourceFactory = {downloadDao.getQueuedDownloads()}
|
pagingSourceFactory = {downloadDao.getQueuedDownloads()}
|
||||||
)
|
)
|
||||||
val cancelledDownloads : Pager<Int, DownloadItem> = Pager(
|
val cancelledDownloads : Pager<Int, DownloadItemSimple> = Pager(
|
||||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||||
pagingSourceFactory = {downloadDao.getCancelledDownloads()}
|
pagingSourceFactory = {downloadDao.getCancelledDownloads()}
|
||||||
)
|
)
|
||||||
val erroredDownloads : Pager<Int, DownloadItem> = Pager(
|
val erroredDownloads : Pager<Int, DownloadItemSimple> = Pager(
|
||||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||||
pagingSourceFactory = {downloadDao.getErroredDownloads()}
|
pagingSourceFactory = {downloadDao.getErroredDownloads()}
|
||||||
)
|
)
|
||||||
val savedDownloads : Pager<Int, DownloadItem> = Pager(
|
val savedDownloads : Pager<Int, DownloadItemSimple> = Pager(
|
||||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
config = PagingConfig(pageSize = 20, initialLoadSize = 20, prefetchDistance = 1),
|
||||||
pagingSourceFactory = {downloadDao.getSavedDownloads()}
|
pagingSourceFactory = {downloadDao.getSavedDownloads()}
|
||||||
)
|
)
|
||||||
|
|
@ -114,6 +115,11 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
downloadDao.deleteSaved()
|
downloadDao.deleteSaved()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun deleteAllWithIDs(ids: List<Long>){
|
||||||
|
downloadDao.deleteAllWithIDs(ids)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun cancelQueued(){
|
suspend fun cancelQueued(){
|
||||||
downloadDao.cancelQueued()
|
downloadDao.cancelQueued()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import android.content.res.Resources
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.LiveData
|
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.AudioPreferences
|
||||||
import com.deniscerri.ytdlnis.database.models.CommandTemplate
|
import com.deniscerri.ytdlnis.database.models.CommandTemplate
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
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.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
|
@ -62,12 +64,12 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
private val commandTemplateDao: CommandTemplateDao
|
private val commandTemplateDao: CommandTemplateDao
|
||||||
private val infoUtil : InfoUtil
|
private val infoUtil : InfoUtil
|
||||||
val allDownloads : Flow<PagingData<DownloadItem>>
|
val allDownloads : Flow<PagingData<DownloadItem>>
|
||||||
val queuedDownloads : Flow<PagingData<DownloadItem>>
|
val queuedDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||||
val activeDownloads : LiveData<List<DownloadItem>>
|
val activeDownloads : LiveData<List<DownloadItem>>
|
||||||
val activeDownloadsCount : LiveData<Int>
|
val activeDownloadsCount : LiveData<Int>
|
||||||
val cancelledDownloads : Flow<PagingData<DownloadItem>>
|
val cancelledDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||||
val erroredDownloads : Flow<PagingData<DownloadItem>>
|
val erroredDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||||
val savedDownloads : Flow<PagingData<DownloadItem>>
|
val savedDownloads : Flow<PagingData<DownloadItemSimple>>
|
||||||
|
|
||||||
private var bestVideoFormat : Format
|
private var bestVideoFormat : Format
|
||||||
private var bestAudioFormat : Format
|
private var bestAudioFormat : Format
|
||||||
|
|
@ -125,35 +127,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
resources = Resources(application.assets, metrics, confTmp)
|
resources = Resources(application.assets, metrics, confTmp)
|
||||||
|
|
||||||
|
|
||||||
val videoFormatValues = resources.getStringArray(R.array.video_formats_values)
|
|
||||||
videoContainer = sharedPreferences.getString("video_format", "Default")
|
videoContainer = sharedPreferences.getString("video_format", "Default")
|
||||||
|
defaultVideoFormats = getGenericVideoFormats()
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
bestVideoFormat = defaultVideoFormats.last()
|
bestVideoFormat = defaultVideoFormats.last()
|
||||||
|
|
||||||
audioContainer = sharedPreferences.getString("audio_format", "mp3")
|
audioContainer = sharedPreferences.getString("audio_format", "mp3")
|
||||||
|
|
@ -200,11 +175,17 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
return repository.getItemByID(id)
|
return repository.getItemByID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSuitableDownloadType(url: String): Type{
|
fun getDownloadType(t: Type, url: String) : Type {
|
||||||
if (urlsForAudioType.any { url.contains(it) }){
|
return when(t){
|
||||||
return Type.audio
|
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 {
|
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 saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||||
|
|
||||||
var type = givenType
|
var type = getDownloadType(givenType, resultItem.url)
|
||||||
if (type == Type.auto){
|
|
||||||
type = getSuitableDownloadType(resultItem.url)
|
|
||||||
}
|
|
||||||
if(type == Type.command && commandTemplateDao.getTotalNumber() == 0) type = Type.video
|
if(type == Type.command && commandTemplateDao.getTotalNumber() == 0) type = Type.video
|
||||||
|
|
||||||
val customFileNameTemplate = when(type) {
|
val customFileNameTemplate = when(type) {
|
||||||
|
|
@ -466,8 +444,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
val audioFormats = resources.getStringArray(R.array.audio_formats)
|
val audioFormats = resources.getStringArray(R.array.audio_formats)
|
||||||
val formats = mutableListOf<Format>()
|
val formats = mutableListOf<Format>()
|
||||||
val containerPreference = sharedPreferences.getString("audio_format", "")
|
val containerPreference = sharedPreferences.getString("audio_format", "")
|
||||||
audioFormatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"","", "",0, it)) }
|
|
||||||
audioFormats.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
|
return formats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -475,8 +453,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
val videoFormats = resources.getStringArray(R.array.video_formats_values)
|
val videoFormats = resources.getStringArray(R.array.video_formats_values)
|
||||||
val formats = mutableListOf<Format>()
|
val formats = mutableListOf<Format>()
|
||||||
val containerPreference = sharedPreferences.getString("video_format", "")
|
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)) }
|
videoFormats.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",0, it)) }
|
||||||
|
formatIDPreference.forEach { formats.add(Format(it, containerPreference!!,"Default","", "",1, it)) }
|
||||||
return formats
|
return formats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -489,8 +467,8 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
val list : MutableList<DownloadItem> = mutableListOf()
|
val list : MutableList<DownloadItem> = mutableListOf()
|
||||||
var preferredType = sharedPreferences.getString("preferred_download_type", "video")
|
var preferredType = sharedPreferences.getString("preferred_download_type", "video")
|
||||||
items.forEach {
|
items.forEach {
|
||||||
if (preferredType == Type.auto.toString()) preferredType = getSuitableDownloadType(it!!.url).toString()
|
preferredType = getDownloadType(Type.valueOf(preferredType!!), it!!.url).toString()
|
||||||
list.add(createDownloadItemFromResult(it!!, Type.valueOf(preferredType!!)))
|
list.add(createDownloadItemFromResult(it, Type.valueOf(preferredType!!)))
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
@ -525,6 +503,11 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
repository.deleteSaved()
|
repository.deleteSaved()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteAllWithID(ids: List<Long>) = viewModelScope.launch(Dispatchers.IO){
|
||||||
|
Log.e("Aa", ids.size.toString())
|
||||||
|
repository.deleteAllWithIDs(ids)
|
||||||
|
}
|
||||||
|
|
||||||
fun cancelQueued() = viewModelScope.launch(Dispatchers.IO) {
|
fun cancelQueued() = viewModelScope.launch(Dispatchers.IO) {
|
||||||
repository.cancelQueued()
|
repository.cancelQueued()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ class ShareActivity : BaseActivity() {
|
||||||
|
|
||||||
private fun showDownloadSheet(it: ResultItem){
|
private fun showDownloadSheet(it: ResultItem){
|
||||||
if (sharedPreferences.getBoolean("download_card", true)){
|
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")
|
bottomSheet.show(supportFragmentManager, "downloadSingleSheet")
|
||||||
}else{
|
}else{
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
lifecycleScope.launch(Dispatchers.IO){
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
|
import androidx.core.view.forEachIndexed
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
|
@ -283,7 +284,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
val providersChipGroup = searchView!!.findViewById<ChipGroup>(R.id.providers)
|
val providersChipGroup = searchView!!.findViewById<ChipGroup>(R.id.providers)
|
||||||
val providers = resources.getStringArray(R.array.search_engines)
|
val providers = resources.getStringArray(R.array.search_engines)
|
||||||
val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList()
|
val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList()
|
||||||
val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch")
|
|
||||||
|
|
||||||
for(i in providersValues.indices){
|
for(i in providersValues.indices){
|
||||||
val provider = providers[i]
|
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
|
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, providersChipGroup, false) as Chip
|
||||||
tmp.text = provider
|
tmp.text = provider
|
||||||
tmp.id = i
|
tmp.id = i
|
||||||
|
tmp.tag = providersValues[i]
|
||||||
if (currentProvider == providerValue) tmp.isChecked = true
|
|
||||||
|
|
||||||
tmp.setOnClickListener {
|
tmp.setOnClickListener {
|
||||||
val editor = sharedPreferences?.edit()
|
val editor = sharedPreferences?.edit()
|
||||||
|
|
@ -308,6 +307,15 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
infoUtil = InfoUtil(requireContext())
|
infoUtil = InfoUtil(requireContext())
|
||||||
searchView!!.addTransitionListener { _, _, newState ->
|
searchView!!.addTransitionListener { _, _, newState ->
|
||||||
if (newState == SearchView.TransitionState.SHOWN) {
|
if (newState == SearchView.TransitionState.SHOWN) {
|
||||||
|
val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch")
|
||||||
|
providersChipGroup.children.forEach {
|
||||||
|
val tmp = providersChipGroup.findViewById<Chip>(it.id)
|
||||||
|
if (tmp.tag == currentProvider) {
|
||||||
|
tmp.isChecked = true
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
val clipboard =
|
val clipboard =
|
||||||
requireContext().getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
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){
|
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")
|
bottomSheet.show(parentFragmentManager, "downloadSingleSheet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){ template ->
|
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){ templates ->
|
||||||
text.text.insert(text.selectionStart, "${template.content} ")
|
templates.forEach {
|
||||||
|
text.text.insert(text.selectionStart, "${it.content} ")
|
||||||
|
}
|
||||||
text.postDelayed({
|
text.postDelayed({
|
||||||
text.requestFocus()
|
text.requestFocus()
|
||||||
imm.showSoftInput(text, 0)
|
imm.showSoftInput(text, 0)
|
||||||
|
|
|
||||||
|
|
@ -132,16 +132,19 @@ class DownloadCommandFragment(private val resultItem: ResultItem, private var cu
|
||||||
commandTemplateCard.setOnClickListener {
|
commandTemplateCard.setOnClickListener {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){
|
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel){
|
||||||
chosenCommandView.editText!!.setText(it.content)
|
chosenCommandView.editText!!.text.clear()
|
||||||
populateCommandCard(commandTemplateCard, it)
|
it.forEach { c ->
|
||||||
|
chosenCommandView.editText!!.text.insert(chosenCommandView.editText!!.selectionStart, "${c.content} ")
|
||||||
|
}
|
||||||
|
populateCommandCard(commandTemplateCard, it.first())
|
||||||
downloadItem.format = Format(
|
downloadItem.format = Format(
|
||||||
it.title,
|
it.first().title,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
it.content
|
it.map { c -> c.content }.joinToString { " " }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
|
import android.util.Log
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
|
@ -328,7 +329,16 @@ class DownloadMultipleBottomSheetDialog(private var items: MutableList<DownloadI
|
||||||
if (items.first().type == DownloadViewModel.Type.command){
|
if (items.first().type == DownloadViewModel.Type.command){
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel) {
|
UiUtil.showCommandTemplates(requireActivity(), commandTemplateViewModel) {
|
||||||
val format = downloadViewModel.generateCommandFormat(it)
|
val format = Format(
|
||||||
|
it.first().title,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
it.joinToString(" ") { c -> c.content }
|
||||||
|
)
|
||||||
|
|
||||||
items.forEach { f ->
|
items.forEach { f ->
|
||||||
f.format = format
|
f.format = format
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,9 +202,7 @@ class CancelledDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClic
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter.clearCheckedItems()
|
adapter.clearCheckedItems()
|
||||||
for (id in selectedObjects){
|
downloadViewModel.deleteAllWithID(selectedObjects)
|
||||||
downloadViewModel.deleteDownload(id)
|
|
||||||
}
|
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,9 +208,7 @@ class ErroredDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickL
|
||||||
adapter.checkedItems.toList()
|
adapter.checkedItems.toList()
|
||||||
}
|
}
|
||||||
adapter.clearCheckedItems()
|
adapter.clearCheckedItems()
|
||||||
for (id in selectedObjects){
|
downloadViewModel.deleteAllWithID(selectedObjects)
|
||||||
downloadViewModel.deleteDownload(id)
|
|
||||||
}
|
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -260,8 +260,8 @@ class QueuedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLi
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toInt().toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toInt().toString())
|
||||||
WorkManager.getInstance(requireContext()).cancelAllWorkByTag(id.toInt().toString())
|
WorkManager.getInstance(requireContext()).cancelAllWorkByTag(id.toInt().toString())
|
||||||
notificationUtil.cancelDownloadNotification(id.toInt())
|
notificationUtil.cancelDownloadNotification(id.toInt())
|
||||||
downloadViewModel.deleteDownload(id)
|
|
||||||
}
|
}
|
||||||
|
downloadViewModel.deleteAllWithID(selectedObjects)
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -222,9 +222,7 @@ class SavedDownloadsFragment : Fragment(), GenericDownloadAdapter.OnItemClickLis
|
||||||
adapter.checkedItems.toList()
|
adapter.checkedItems.toList()
|
||||||
}
|
}
|
||||||
adapter.clearCheckedItems()
|
adapter.clearCheckedItems()
|
||||||
withContext(Dispatchers.IO) {
|
downloadViewModel.deleteAllWithID(selectedObjects)
|
||||||
downloadViewModel.reQueueDownloadItems(selectedObjects)
|
|
||||||
}
|
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.deniscerri.ytdlnis.ui.more
|
package com.deniscerri.ytdlnis.ui.more
|
||||||
|
|
||||||
|
import android.app.ActionBar.LayoutParams
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -8,8 +9,8 @@ import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.FileObserver
|
|
||||||
import android.os.PersistableBundle
|
import android.os.PersistableBundle
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
@ -22,7 +23,6 @@ import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.view.forEach
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
|
@ -62,8 +62,8 @@ class TerminalActivity : BaseActivity() {
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private var downloadID by Delegates.notNull<Int>()
|
private var downloadID by Delegates.notNull<Int>()
|
||||||
private lateinit var downloadFile : File
|
private lateinit var downloadFile : File
|
||||||
private lateinit var observer: FileObserver
|
|
||||||
private lateinit var imm : InputMethodManager
|
private lateinit var imm : InputMethodManager
|
||||||
|
private lateinit var metrics: DisplayMetrics
|
||||||
var context: Context? = null
|
var context: Context? = null
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -82,6 +82,8 @@ class TerminalActivity : BaseActivity() {
|
||||||
|
|
||||||
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
commandTemplateViewModel = ViewModelProvider(this)[CommandTemplateViewModel::class.java]
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
metrics = DisplayMetrics()
|
||||||
|
windowManager.defaultDisplay.getMetrics(metrics)
|
||||||
|
|
||||||
|
|
||||||
bottomAppBar = findViewById(R.id.bottomAppBar)
|
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()
|
Toast.makeText(context, getString(R.string.add_template_first), Toast.LENGTH_SHORT).show()
|
||||||
}else{
|
}else{
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
UiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ template ->
|
UiUtil.showCommandTemplates(this@TerminalActivity, commandTemplateViewModel){ templates ->
|
||||||
input!!.text.insert(input!!.selectionStart, template.content + " ")
|
templates.forEach {c ->
|
||||||
|
input!!.text.insert(input!!.selectionStart, c.content + " ")
|
||||||
|
}
|
||||||
input!!.postDelayed({
|
input!!.postDelayed({
|
||||||
input!!.requestFocus()
|
input!!.requestFocus()
|
||||||
imm.showSoftInput(input!!, 0)
|
imm.showSoftInput(input!!, 0)
|
||||||
|
|
@ -146,7 +150,7 @@ class TerminalActivity : BaseActivity() {
|
||||||
|
|
||||||
output = findViewById(R.id.custom_command_output)
|
output = findViewById(R.id.custom_command_output)
|
||||||
output!!.setTextIsSelectable(true)
|
output!!.setTextIsSelectable(true)
|
||||||
output!!.setHorizontallyScrolling(true)
|
output!!.layoutParams!!.width = LayoutParams.WRAP_CONTENT
|
||||||
input = findViewById(R.id.command_edittext)
|
input = findViewById(R.id.command_edittext)
|
||||||
input!!.requestFocus()
|
input!!.requestFocus()
|
||||||
fab = findViewById(R.id.command_fab)
|
fab = findViewById(R.id.command_fab)
|
||||||
|
|
@ -168,38 +172,6 @@ class TerminalActivity : BaseActivity() {
|
||||||
notificationUtil = NotificationUtil(this)
|
notificationUtil = NotificationUtil(this)
|
||||||
handleIntent(intent)
|
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)
|
WorkManager.getInstance(this)
|
||||||
.getWorkInfosForUniqueWorkLiveData(downloadID.toString())
|
.getWorkInfosForUniqueWorkLiveData(downloadID.toString())
|
||||||
.observe(this){ list ->
|
.observe(this){ list ->
|
||||||
|
|
@ -269,7 +241,6 @@ class TerminalActivity : BaseActivity() {
|
||||||
scrollView.id = R.id.horizontalscroll_output
|
scrollView.id = R.id.horizontalscroll_output
|
||||||
parent.addView(scrollView, 0)
|
parent.addView(scrollView, 0)
|
||||||
}
|
}
|
||||||
output?.setHorizontallyScrolling(output?.canScrollHorizontally(1) != true)
|
|
||||||
}
|
}
|
||||||
R.id.export_clipboard -> {
|
R.id.export_clipboard -> {
|
||||||
lifecycleScope.launch(Dispatchers.IO){
|
lifecycleScope.launch(Dispatchers.IO){
|
||||||
|
|
@ -317,12 +288,10 @@ class TerminalActivity : BaseActivity() {
|
||||||
private fun hideCancelFab() {
|
private fun hideCancelFab() {
|
||||||
fab!!.text = getString(R.string.run_command)
|
fab!!.text = getString(R.string.run_command)
|
||||||
fab!!.setIconResource(R.drawable.ic_baseline_keyboard_arrow_right_24)
|
fab!!.setIconResource(R.drawable.ic_baseline_keyboard_arrow_right_24)
|
||||||
topAppBar!!.menu.forEach { it.isEnabled = true }
|
|
||||||
}
|
}
|
||||||
private fun showCancelFab() {
|
private fun showCancelFab() {
|
||||||
fab!!.text = getString(R.string.cancel_download)
|
fab!!.text = getString(R.string.cancel_download)
|
||||||
fab!!.setIconResource(R.drawable.ic_cancel)
|
fab!!.setIconResource(R.drawable.ic_cancel)
|
||||||
topAppBar!!.menu.forEach { it.isEnabled = false }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var commandPathResultLauncher = registerForActivityResult(
|
private var commandPathResultLauncher = registerForActivityResult(
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
override val title: Int = R.string.general
|
override val title: Int = R.string.general
|
||||||
|
|
||||||
private var language: ListPreference? = null
|
private var language: ListPreference? = null
|
||||||
|
private var language13: Preference? = null
|
||||||
private var theme: ListPreference? = null
|
private var theme: ListPreference? = null
|
||||||
private var accent: ListPreference? = null
|
private var accent: ListPreference? = null
|
||||||
private var highContrast: SwitchPreferenceCompat? = null
|
private var highContrast: SwitchPreferenceCompat? = null
|
||||||
|
|
@ -50,6 +51,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
language = findPreference("app_language")
|
language = findPreference("app_language")
|
||||||
|
language13 = findPreference("app_language_13")
|
||||||
theme = findPreference("ytdlnis_theme")
|
theme = findPreference("ytdlnis_theme")
|
||||||
accent = findPreference("theme_accent")
|
accent = findPreference("theme_accent")
|
||||||
highContrast = findPreference("high_contrast")
|
highContrast = findPreference("high_contrast")
|
||||||
|
|
@ -63,18 +65,32 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
entries.add(Locale(it).getDisplayName(Locale(it)))
|
entries.add(Locale(it).getDisplayName(Locale(it)))
|
||||||
}
|
}
|
||||||
language!!.entries = entries.toTypedArray()
|
language!!.entries = entries.toTypedArray()
|
||||||
}else{
|
|
||||||
language!!.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if(language!!.value == null) language!!.value = Locale.getDefault().language
|
if(language!!.value == null) language!!.value = Locale.getDefault().language
|
||||||
language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value))
|
language!!.summary = Locale(language!!.value).getDisplayLanguage(Locale(language!!.value))
|
||||||
language!!.onPreferenceChangeListener =
|
|
||||||
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
language!!.onPreferenceChangeListener =
|
||||||
language!!.summary = Locale(newValue.toString()).getDisplayLanguage(Locale(newValue.toString()))
|
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||||
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(newValue.toString()))
|
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
|
true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
theme!!.summary = theme!!.entry
|
theme!!.summary = theme!!.entry
|
||||||
theme!!.onPreferenceChangeListener =
|
theme!!.onPreferenceChangeListener =
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
historyItems.forEach {
|
historyItems.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -273,7 +273,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -287,7 +287,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -315,7 +315,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -330,7 +330,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
it.useAsExtraCommand = false
|
it.useAsExtraCommand = false
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +344,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
items.forEach {
|
items.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -358,7 +358,7 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
}
|
}
|
||||||
val arr = JsonArray()
|
val arr = JsonArray()
|
||||||
historyItems.forEach {
|
historyItems.forEach {
|
||||||
arr.add(JsonParser().parse(Gson().toJson(it)).asJsonObject)
|
arr.add(JsonParser.parseString(Gson().toJson(it)).asJsonObject)
|
||||||
}
|
}
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
@ -380,7 +380,6 @@ class MainSettingsFragment : PreferenceFragmentCompat() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val preferences =
|
val preferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
val editor = preferences.edit()
|
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
val ip = requireContext().contentResolver.openInputStream(result.data!!.data!!)
|
val ip = requireContext().contentResolver.openInputStream(result.data!!.data!!)
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ object FileUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertFileSize(s: Long): String{
|
fun convertFileSize(s: Long): String{
|
||||||
if (s <= 0) return "?"
|
if (s <= 1) return "?"
|
||||||
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||||
val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt()
|
val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt()
|
||||||
val symbols = DecimalFormatSymbols(Locale.US)
|
val symbols = DecimalFormatSymbols(Locale.US)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.content.SharedPreferences
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.util.Patterns
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
|
@ -547,7 +548,6 @@ class InfoUtil(private val context: Context) {
|
||||||
|
|
||||||
fun getFromYTDL(query: String): ArrayList<ResultItem?> {
|
fun getFromYTDL(query: String): ArrayList<ResultItem?> {
|
||||||
items = ArrayList()
|
items = ArrayList()
|
||||||
val webpage_urls = mutableListOf<String>()
|
|
||||||
val searchEngine = sharedPreferences.getString("search_engine", "ytsearch")
|
val searchEngine = sharedPreferences.getString("search_engine", "ytsearch")
|
||||||
try {
|
try {
|
||||||
val request : YoutubeDLRequest
|
val request : YoutubeDLRequest
|
||||||
|
|
@ -656,7 +656,11 @@ class InfoUtil(private val context: Context) {
|
||||||
val url = if (jsonObject.has("url")){
|
val url = if (jsonObject.has("url")){
|
||||||
jsonObject.getString("url")
|
jsonObject.getString("url")
|
||||||
}else{
|
}else{
|
||||||
jsonObject.getString("webpage_url")
|
if (Patterns.WEB_URL.matcher(query).matches()){
|
||||||
|
query
|
||||||
|
}else{
|
||||||
|
jsonObject.getString("webpage_url")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items.add(ResultItem(0,
|
items.add(ResultItem(0,
|
||||||
|
|
@ -672,10 +676,6 @@ class InfoUtil(private val context: Context) {
|
||||||
chapters
|
chapters
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
webpage_urls.add(jsonObject.getString("webpage_url"))
|
|
||||||
}
|
|
||||||
if (items.size == 1){
|
|
||||||
items[0]?.url = webpage_urls.first()
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Looper.prepare().run {
|
Looper.prepare().run {
|
||||||
|
|
@ -970,20 +970,6 @@ class InfoUtil(private val context: Context) {
|
||||||
downDir.mkdirs()
|
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)
|
val aria2 = sharedPreferences.getBoolean("aria2", false)
|
||||||
if (aria2) {
|
if (aria2) {
|
||||||
request.addOption("--downloader", "libaria2c.so")
|
request.addOption("--downloader", "libaria2c.so")
|
||||||
|
|
@ -1001,6 +987,7 @@ class InfoUtil(private val context: Context) {
|
||||||
|
|
||||||
val limitRate = sharedPreferences.getString("limit_rate", "")
|
val limitRate = sharedPreferences.getString("limit_rate", "")
|
||||||
if (limitRate != "") request.addOption("-r", limitRate!!)
|
if (limitRate != "") request.addOption("-r", limitRate!!)
|
||||||
|
request.addOption("--trim-filenames", 120)
|
||||||
if(downloadItem.type != DownloadViewModel.Type.command){
|
if(downloadItem.type != DownloadViewModel.Type.command){
|
||||||
if (downloadItem.SaveThumb) {
|
if (downloadItem.SaveThumb) {
|
||||||
request.addOption("--write-thumbnail")
|
request.addOption("--write-thumbnail")
|
||||||
|
|
@ -1034,12 +1021,12 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(downloadItem.title.isNotBlank()){
|
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()){
|
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()){
|
if (downloadItem.downloadSections.isNotBlank()){
|
||||||
downloadItem.downloadSections.split(";").forEach {
|
downloadItem.downloadSections.split(";").forEach {
|
||||||
|
|
@ -1077,6 +1064,21 @@ class InfoUtil(private val context: Context) {
|
||||||
if (sharedPreferences.getBoolean("write_description", false)){
|
if (sharedPreferences.getBoolean("write_description", false)){
|
||||||
request.addOption("--write-description")
|
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)) {
|
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 (! request.hasOption("--convert-thumbnails")) request.addOption("--convert-thumbnails", "jpg")
|
||||||
if (sharedPreferences.getBoolean("crop_thumbnail", true)){
|
if (sharedPreferences.getBoolean("crop_thumbnail", true)){
|
||||||
try {
|
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)'\\\"\""
|
val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||||
config.writeText(configData)
|
config.writeText(configData)
|
||||||
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
||||||
|
|
@ -1156,7 +1158,7 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadItem.customFileNameTemplate.isNotBlank()){
|
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")
|
request.addOption("-o", "chapter:%(section_title)s.%(ext)s")
|
||||||
}else{
|
}else{
|
||||||
if (downloadItem.customFileNameTemplate.isNotBlank()){
|
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("\"\"", "\" \"")
|
var final = java.lang.String.join(" ", arr).replace("\"\"", "\" \"")
|
||||||
val ppas = "--config(-locations)? \"(.*?)\"".toRegex().findAll(final)
|
val ppas = "--config(-locations)? \"(.*?)\"".toRegex().findAll(final)
|
||||||
ppas.forEach {
|
ppas.forEach {res ->
|
||||||
val path = "\"(.*?)\"".toRegex().find(it.value)?.value?.replace("\"", "")
|
val path = "\"(.*?)\"".toRegex().find(res.value)?.value?.replace("\"", "")
|
||||||
final = final.replace(it.value, "")
|
val newVal = runCatching {
|
||||||
final += " ${File(path ?: "").readText()}"
|
File(path ?: "").readText()
|
||||||
|
}.onFailure {
|
||||||
|
res.value
|
||||||
|
}.getOrDefault("")
|
||||||
|
|
||||||
|
final = final.replace(res.value, newVal)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return final
|
return final
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
|
@ -543,14 +544,14 @@ object UiUtil {
|
||||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
bottomSheet.setContentView(R.layout.format_details_sheet)
|
bottomSheet.setContentView(R.layout.format_details_sheet)
|
||||||
|
|
||||||
val formatIdParent = bottomSheet.findViewById<LinearLayout>(R.id.format_id_parent)
|
val formatIdParent = bottomSheet.findViewById<ConstraintLayout>(R.id.format_id_parent)
|
||||||
val formatURLParent = bottomSheet.findViewById<LinearLayout>(R.id.format_url_parent)
|
val formatURLParent = bottomSheet.findViewById<ConstraintLayout>(R.id.format_url_parent)
|
||||||
val containerParent = bottomSheet.findViewById<LinearLayout>(R.id.container_parent)
|
val containerParent = bottomSheet.findViewById<ConstraintLayout>(R.id.container_parent)
|
||||||
val codecParent = bottomSheet.findViewById<LinearLayout>(R.id.codec_parent)
|
val codecParent = bottomSheet.findViewById<ConstraintLayout>(R.id.codec_parent)
|
||||||
val filesizeParent = bottomSheet.findViewById<LinearLayout>(R.id.filesize_parent)
|
val filesizeParent = bottomSheet.findViewById<ConstraintLayout>(R.id.filesize_parent)
|
||||||
val formatnoteParent = bottomSheet.findViewById<LinearLayout>(R.id.format_note_parent)
|
val formatnoteParent = bottomSheet.findViewById<ConstraintLayout>(R.id.format_note_parent)
|
||||||
val fpsParent = bottomSheet.findViewById<LinearLayout>(R.id.fps_parent)
|
val fpsParent = bottomSheet.findViewById<ConstraintLayout>(R.id.fps_parent)
|
||||||
val asrParent = bottomSheet.findViewById<LinearLayout>(R.id.asr_parent)
|
val asrParent = bottomSheet.findViewById<ConstraintLayout>(R.id.asr_parent)
|
||||||
|
|
||||||
if (format.format_id.isBlank()) formatIdParent?.visibility = View.GONE
|
if (format.format_id.isBlank()) formatIdParent?.visibility = View.GONE
|
||||||
else {
|
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<CommandTemplate>) -> Unit) {
|
||||||
val bottomSheet = BottomSheetDialog(activity)
|
val bottomSheet = BottomSheetDialog(activity)
|
||||||
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
bottomSheet.setContentView(R.layout.command_template_list)
|
bottomSheet.setContentView(R.layout.command_template_list)
|
||||||
|
|
@ -701,17 +702,33 @@ object UiUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
linearLayout!!.removeAllViews()
|
linearLayout!!.removeAllViews()
|
||||||
|
val selectedItems = mutableListOf<CommandTemplate>()
|
||||||
|
val ok = bottomSheet.findViewById<MaterialButton>(R.id.command_ok)
|
||||||
|
ok?.isEnabled = list.size == 1
|
||||||
|
|
||||||
list.forEach {template ->
|
list.forEach {template ->
|
||||||
val item = activity.layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as MaterialCardView
|
val item = activity.layoutInflater.inflate(R.layout.command_template_item, linearLayout, false) as MaterialCardView
|
||||||
item.findViewById<TextView>(R.id.title).text = template.title
|
item.findViewById<TextView>(R.id.title).text = template.title
|
||||||
item.findViewById<TextView>(R.id.content).text = template.content
|
item.findViewById<TextView>(R.id.content).text = template.content
|
||||||
item.setOnClickListener {
|
item.setOnClickListener {
|
||||||
itemSelected(template)
|
if (selectedItems.contains(template)){
|
||||||
bottomSheet.cancel()
|
selectedItems.remove(template)
|
||||||
|
(it as MaterialCardView).isChecked = false
|
||||||
|
}else{
|
||||||
|
selectedItems.add(template)
|
||||||
|
(it as MaterialCardView).isChecked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
ok?.isEnabled = selectedItems.isNotEmpty()
|
||||||
}
|
}
|
||||||
linearLayout.addView(item)
|
linearLayout.addView(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok?.setOnClickListener {
|
||||||
|
itemSelected(selectedItems.ifEmpty { listOf(list.first()) })
|
||||||
|
bottomSheet.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
bottomSheet.show()
|
bottomSheet.show()
|
||||||
bottomSheet.window!!.setLayout(
|
bottomSheet.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
|
@ -913,9 +930,6 @@ object UiUtil {
|
||||||
) { _: DialogInterface?, _: Int -> }
|
) { _: DialogInterface?, _: Int -> }
|
||||||
|
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
editText.doOnTextChanged { _, _, _, _ ->
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
|
||||||
}
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
editText!!.postDelayed({
|
editText!!.postDelayed({
|
||||||
|
|
@ -1016,9 +1030,6 @@ object UiUtil {
|
||||||
) { _: DialogInterface?, _: Int -> }
|
) { _: DialogInterface?, _: Int -> }
|
||||||
|
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
editText.doOnTextChanged { _, _, _, _ ->
|
|
||||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = editText.text.isNotEmpty()
|
|
||||||
}
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = context.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
editText!!.postDelayed({
|
editText!!.postDelayed({
|
||||||
|
|
|
||||||
|
|
@ -116,11 +116,7 @@ class DownloadWorker(
|
||||||
"Title: ${downloadItem.title}\n" +
|
"Title: ${downloadItem.title}\n" +
|
||||||
"URL: ${downloadItem.url}\n" +
|
"URL: ${downloadItem.url}\n" +
|
||||||
"Type: ${downloadItem.type}\n" +
|
"Type: ${downloadItem.type}\n" +
|
||||||
if (downloadItem.type != DownloadViewModel.Type.command){
|
"Command:\n ${infoUtil.parseYTDLRequestString(request)}\n\n",
|
||||||
"Format: ${downloadItem.format}\n\n"
|
|
||||||
}
|
|
||||||
else { "" } +
|
|
||||||
"Command:\n ${infoUtil.parseYTDLRequestString(request)} ${downloadItem.extraCommands}\n\n",
|
|
||||||
downloadItem.format,
|
downloadItem.format,
|
||||||
downloadItem.type,
|
downloadItem.type,
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,13 @@ class TerminalDownloadWorker(
|
||||||
}
|
}
|
||||||
|
|
||||||
YoutubeDL.getInstance().execute(request, itemId.toString()){ progress, _, line ->
|
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)
|
val title: String = command.take(65)
|
||||||
notificationUtil.updateDownloadNotification(
|
notificationUtil.updateDownloadNotification(
|
||||||
itemId,
|
itemId,
|
||||||
|
|
@ -128,32 +134,46 @@ class TerminalDownloadWorker(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputFile.appendText("${it.out}\n")
|
return runBlocking {
|
||||||
if (logDownloads){
|
it.out.chunked(10000).forEach {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
setProgress(workDataOf("progress" to 100, "output" to it, "id" to itemId, "log" to logDownloads))
|
||||||
logRepo.update(it.out, logItem.id)
|
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 {
|
}.onFailure {
|
||||||
if (it is YoutubeDL.CanceledException) {
|
if (it is YoutubeDL.CanceledException) {
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
outputFile.appendText("\n${it.message}\n")
|
|
||||||
if (logDownloads){
|
return runBlocking {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
it.message?.chunked(10000)?.forEach {
|
||||||
if (it.message != null){
|
setProgress(workDataOf("progress" to 100, "output" to it, "id" to itemId, "log" to logDownloads))
|
||||||
logRepo.update(it.message!!, logItem.id)
|
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()
|
return Result.success()
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,12 @@
|
||||||
android:id="@+id/bottom_sheet_title"
|
android:id="@+id/bottom_sheet_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="false"
|
||||||
android:text="@string/command_templates"
|
android:text="@string/command_templates"
|
||||||
android:textSize="25sp"
|
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_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
@ -39,6 +43,18 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" />
|
app:layout_constraintTop_toBottomOf="@+id/bottom_sheet_title" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/command_ok"
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="all"
|
||||||
|
android:text="@string/ok"
|
||||||
|
app:icon="@drawable/ic_check"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
@ -15,37 +16,41 @@
|
||||||
android:layout_margin="20dp"
|
android:layout_margin="20dp"
|
||||||
android:layout_height="wrap_content"/>
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/format_id_parent"
|
android:id="@+id/format_id_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
|
||||||
android:paddingHorizontal="10dp"
|
android:paddingHorizontal="10dp"
|
||||||
android:weightSum="100"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:text="@string/format_id"
|
android:text="@string/format_id"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_margin="10dp"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_height="wrap_content"/>
|
app:layout_constraintEnd_toStartOf="@+id/format_id_value"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/format_id_value"
|
android:id="@+id/format_id_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/format_url_parent"
|
android:id="@+id/format_url_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -56,29 +61,35 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView2"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:text="@string/url"
|
android:text="@string/url"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_margin="10dp"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_height="wrap_content"/>
|
app:layout_constraintEnd_toStartOf="@+id/format_url_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/format_url_value"
|
android:id="@+id/format_url_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:maxLines="3"
|
android:layout_height="wrap_content"
|
||||||
android:ellipsize="end"
|
|
||||||
android:layout_weight="70"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
|
android:ellipsize="end"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:maxLines="3"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/container_parent"
|
android:id="@+id/container_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -89,26 +100,32 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView3"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
android:maxLines="2"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
android:textSize="14sp"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/container"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:layout_height="wrap_content"/>
|
android:maxLines="2"
|
||||||
|
android:text="@string/container"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/container_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/container_value"
|
android:id="@+id/container_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/codec_parent"
|
android:id="@+id/codec_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -119,25 +136,31 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView4"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
android:textSize="14sp"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/codec"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:layout_height="wrap_content"/>
|
android:text="@string/codec"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/codec_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/codec_value"
|
android:id="@+id/codec_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/filesize_parent"
|
android:id="@+id/filesize_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -148,25 +171,31 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView5"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
android:text="@string/file_size"
|
android:text="@string/file_size"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_margin="10dp"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_height="wrap_content"/>
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/filesize_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/filesize_value"
|
android:id="@+id/filesize_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/format_note_parent"
|
android:id="@+id/format_note_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -177,25 +206,30 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:text="@string/quality"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="30"
|
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:layout_height="wrap_content"/>
|
android:text="@string/quality"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/format_note_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/format_note_value"
|
android:id="@+id/format_note_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/fps_parent"
|
android:id="@+id/fps_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -206,25 +240,31 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView6"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
android:text="FPS"
|
android:text="FPS"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_margin="10dp"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_height="wrap_content"/>
|
app:layout_constraintEnd_toStartOf="@+id/fps_value"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/fps_value"
|
android:id="@+id/fps_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/asr_parent"
|
android:id="@+id/asr_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -235,23 +275,29 @@
|
||||||
android:orientation="horizontal" >
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:id="@+id/textView7"
|
||||||
android:layout_weight="30"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
android:text="@string/audio_samplerate"
|
android:text="@string/audio_samplerate"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:layout_margin="10dp"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_height="wrap_content"/>
|
app:layout_constraintEnd_toStartOf="@+id/asr_value"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/asr_value"
|
android:id="@+id/asr_value"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_weight="70"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="14sp"
|
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
android:layout_height="wrap_content"/>
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/format"
|
android:text="@string/format"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:singleLine="false"
|
||||||
android:textSize="25sp"
|
android:textSize="25sp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
|
||||||
|
|
@ -788,9 +788,8 @@
|
||||||
<item>@string/defaultValue</item>
|
<item>@string/defaultValue</item>
|
||||||
<item tools:ignore="Typos">AV1</item>
|
<item tools:ignore="Typos">AV1</item>
|
||||||
<item>VP9</item>
|
<item>VP9</item>
|
||||||
<item tools:ignore="Typos">AVC</item>
|
<item tools:ignore="Typos">AVC (H264)</item>
|
||||||
<item>H265</item>
|
<item>HEVC (H265)</item>
|
||||||
<item>H264</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="video_codec_values">
|
<string-array name="video_codec_values">
|
||||||
|
|
@ -799,8 +798,5 @@
|
||||||
<item>vp</item>
|
<item>vp</item>
|
||||||
<item>avc</item>
|
<item>avc</item>
|
||||||
<item>hev</item>
|
<item>hev</item>
|
||||||
<item>h264</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string name="auto">Auto</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -302,4 +302,5 @@
|
||||||
<string name="use_scheduler">Download On Schedule</string>
|
<string name="use_scheduler">Download On Schedule</string>
|
||||||
<string name="update_app_beta">Beta Releases</string>
|
<string name="update_app_beta">Beta Releases</string>
|
||||||
<string name="update_app_beta_summary">Enroll in the beta program. It may contain bugs.</string>
|
<string name="update_app_beta_summary">Enroll in the beta program. It may contain bugs.</string>
|
||||||
|
<string name="auto">Auto</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -11,6 +11,12 @@
|
||||||
app:summary="en"
|
app:summary="en"
|
||||||
app:title="@string/language" />
|
app:title="@string/language" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:icon="@drawable/baseline_translate_24"
|
||||||
|
app:key="app_language_13"
|
||||||
|
app:summary="en"
|
||||||
|
app:title="@string/language" />
|
||||||
|
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:entries="@array/themes"
|
android:entries="@array/themes"
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
app:key="piped_instance"
|
app:key="piped_instance"
|
||||||
app:defaultValue="https://api.piped.projectsegfau.lt"
|
app:defaultValue=""
|
||||||
android:summary="@string/piped_instance_summary"
|
android:summary="@string/piped_instance_summary"
|
||||||
app:title="@string/piped_instance" />
|
app:title="@string/piped_instance" />
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue