added other download cards and recyclerview for cards to be queued for download
This commit is contained in:
parent
d124b8fb5f
commit
2371ab734d
22 changed files with 850 additions and 735 deletions
|
|
@ -320,7 +320,7 @@
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/schedule/baseline_schedule_24.xml" />
|
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/keyboard_double_arrow_down/baseline_keyboard_double_arrow_down_24.xml" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
|
|
@ -331,7 +331,7 @@
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="color" value="00a6ff" />
|
<entry key="color" value="00a6ff" />
|
||||||
<entry key="outputName" value="ic_clock" />
|
<entry key="outputName" value="ic_concurrent_downloads" />
|
||||||
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
|
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "6c48acc2155f9a895971bd84c84b7d4e",
|
"identityHash": "5939be553c41327f4f64e1d62d008968",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "results",
|
"tableName": "results",
|
||||||
|
|
@ -198,7 +198,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "downloads",
|
"tableName": "downloads",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `audioQualityId` TEXT NOT NULL, `videoQualityId` TEXT NOT NULL, `customTemplateId` INTEGER NOT NULL, `audioFormat` TEXT NOT NULL, `videoFormat` TEXT NOT NULL, `formatDesc` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `audioQualityId` TEXT NOT NULL, `videoQualityId` TEXT NOT NULL, `customTemplateId` INTEGER NOT NULL, `audioFormat` TEXT NOT NULL, `videoFormat` TEXT NOT NULL, `formatDesc` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "url",
|
"fieldPath": "url",
|
||||||
|
|
@ -303,6 +303,24 @@
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "embedSubs",
|
||||||
|
"columnName": "embedSubs",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "addChapters",
|
||||||
|
"columnName": "addChapters",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "SaveThumb",
|
||||||
|
"columnName": "SaveThumb",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "status",
|
"fieldPath": "status",
|
||||||
"columnName": "status",
|
"columnName": "status",
|
||||||
|
|
@ -368,7 +386,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6c48acc2155f9a895971bd84c84b7d4e')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5939be553c41327f4f64e1d62d008968')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,8 @@ import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.work.Configuration
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
|
|
@ -23,12 +25,12 @@ import io.reactivex.observers.DisposableCompletableObserver
|
||||||
import io.reactivex.plugins.RxJavaPlugins
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
class App : Application() {
|
class App : Application() {
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||||
notificationUtil = NotificationUtil(this)
|
|
||||||
createNotificationChannels()
|
createNotificationChannels()
|
||||||
PreferenceManager.setDefaultValues(
|
PreferenceManager.setDefaultValues(
|
||||||
this,
|
this,
|
||||||
|
|
@ -37,6 +39,15 @@ class App : Application() {
|
||||||
R.xml.root_preferences,
|
R.xml.root_preferences,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
WorkManager.initialize(
|
||||||
|
this@App,
|
||||||
|
Configuration.Builder()
|
||||||
|
.setExecutor(Executors.newFixedThreadPool(
|
||||||
|
getSharedPreferences("root_preferences", MODE_PRIVATE)
|
||||||
|
.getInt("concurrent_downloads", 1)))
|
||||||
|
.build())
|
||||||
|
|
||||||
configureRxJavaErrorHandler()
|
configureRxJavaErrorHandler()
|
||||||
Completable.fromAction { initLibraries() }.subscribeOn(Schedulers.io())
|
Completable.fromAction { initLibraries() }.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
|
@ -79,12 +90,11 @@ class App : Application() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotificationChannels() {
|
private fun createNotificationChannels() {
|
||||||
|
val notificationUtil = NotificationUtil(this)
|
||||||
notificationUtil.createNotificationChannel()
|
notificationUtil.createNotificationChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "App"
|
private const val TAG = "App"
|
||||||
@SuppressLint("StaticFieldLeak")
|
|
||||||
lateinit var notificationUtil: NotificationUtil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,10 +9,7 @@ import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.*
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import androidx.work.workDataOf
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.service.DownloadInfo
|
import com.deniscerri.ytdlnis.service.DownloadInfo
|
||||||
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
import com.deniscerri.ytdlnis.service.IDownloaderListener
|
||||||
|
|
@ -32,6 +29,7 @@ import io.reactivex.schedulers.Schedulers
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import java.util.concurrent.Executors
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -43,7 +41,6 @@ class DownloaderService : Service() {
|
||||||
private val downloadInfo = DownloadInfo()
|
private val downloadInfo = DownloadInfo()
|
||||||
private var downloadQueue = LinkedList<ResultItem>()
|
private var downloadQueue = LinkedList<ResultItem>()
|
||||||
private val compositeDisposable = CompositeDisposable()
|
private val compositeDisposable = CompositeDisposable()
|
||||||
private val notificationUtil = App.notificationUtil
|
|
||||||
private var context: Context? = null
|
private var context: Context? = null
|
||||||
var downloadProcessID = "processID"
|
var downloadProcessID = "processID"
|
||||||
private var downloadNotificationID = 0
|
private var downloadNotificationID = 0
|
||||||
|
|
@ -59,11 +56,11 @@ class DownloaderService : Service() {
|
||||||
if (!downloadQueue.isEmpty()) {
|
if (!downloadQueue.isEmpty()) {
|
||||||
title = downloadQueue.peek()?.title
|
title = downloadQueue.peek()?.title
|
||||||
}
|
}
|
||||||
notificationUtil.updateDownloadNotification(
|
// notificationUtil.updateDownloadNotification(
|
||||||
downloadNotificationID,
|
// downloadNotificationID,
|
||||||
line!!, progress.toInt(), downloadQueue.size, title,
|
// line!!, progress.toInt(), downloadQueue.size, title,
|
||||||
notificationChannelID
|
// notificationChannelID
|
||||||
)
|
// )
|
||||||
try {
|
try {
|
||||||
for (activity in activities.keys) {
|
for (activity in activities.keys) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
|
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) :
|
||||||
|
ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder?>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) :
|
||||||
|
RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.download_multiple_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.home_download_multiple_card, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val item = getItem(position)
|
||||||
|
val card = holder.cardView
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.result_image_view)
|
||||||
|
val imageURL = item!!.thumb
|
||||||
|
if (imageURL.isNotEmpty()) {
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
|
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
|
||||||
|
} else {
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
|
||||||
|
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val itemTitle = card.findViewById<TextView>(R.id.result_title)
|
||||||
|
var title = item.title
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
itemTitle.text = title
|
||||||
|
|
||||||
|
// Author ----------------------------------
|
||||||
|
val author = card.findViewById<TextView>(R.id.author)
|
||||||
|
author.text = item.author
|
||||||
|
|
||||||
|
// Format
|
||||||
|
val format = card.findViewById<TextView>(R.id.format)
|
||||||
|
format.text = item.ext
|
||||||
|
|
||||||
|
// Quality
|
||||||
|
val quality = card.findViewById<TextView>(R.id.quality)
|
||||||
|
quality.text = item.formatDesc
|
||||||
|
|
||||||
|
// File Size
|
||||||
|
val fileSize = card.findViewById<TextView>(R.id.filesize)
|
||||||
|
fileSize.text = item.filesize
|
||||||
|
|
||||||
|
// Type Icon Button
|
||||||
|
val btn = card.findViewById<MaterialButton>(R.id.download_type)
|
||||||
|
|
||||||
|
when(item.type) {
|
||||||
|
"audio" -> {
|
||||||
|
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music)
|
||||||
|
}
|
||||||
|
"video" -> {
|
||||||
|
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video)
|
||||||
|
}
|
||||||
|
"command" -> {
|
||||||
|
btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_baseline_keyboard_arrow_right_24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
card.setOnClickListener {
|
||||||
|
onItemClickListener.onCardClick(item.id!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onCardClick(itemID: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> =
|
||||||
|
object : DiffUtil.ItemCallback<DownloadItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
||||||
|
return oldItem.id === newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
||||||
|
return oldItem.url == newItem.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,8 +15,11 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active'")
|
||||||
fun getActiveDownloads() : LiveData<List<DownloadItem>>
|
fun getActiveDownloads() : LiveData<List<DownloadItem>>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM downloads WHERE status='Queued'")
|
||||||
|
fun getQueuedDownloads() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE workID=:workID")
|
@Query("SELECT * FROM downloads WHERE workID=:workID")
|
||||||
fun getDownloadsByWorkId(workID: Int) : List<DownloadItem>
|
fun getDownloadByWorkId(workID: Int) : DownloadItem
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
|
||||||
fun getDownloadById(id: Int) : DownloadItem
|
fun getDownloadById(id: Int) : DownloadItem
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ data class DownloadItem(
|
||||||
val embedSubs: Boolean,
|
val embedSubs: Boolean,
|
||||||
val addChapters: Boolean,
|
val addChapters: Boolean,
|
||||||
val SaveThumb: Boolean,
|
val SaveThumb: Boolean,
|
||||||
|
var ext: String,
|
||||||
|
var filesize: String,
|
||||||
@ColumnInfo(defaultValue = "Queued")
|
@ColumnInfo(defaultValue = "Queued")
|
||||||
val status: String,
|
var status: String,
|
||||||
val workID: Int
|
val workID: Int
|
||||||
){
|
){
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads()
|
val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads()
|
||||||
val activeDownloads : LiveData<List<DownloadItem>> = downloadDao.getActiveDownloads()
|
val activeDownloads : LiveData<List<DownloadItem>> = downloadDao.getActiveDownloads()
|
||||||
|
|
||||||
|
enum class status {
|
||||||
|
Active, Queued, Errored
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun insert(item: DownloadItem){
|
suspend fun insert(item: DownloadItem){
|
||||||
downloadDao.insert(item)
|
downloadDao.insert(item)
|
||||||
}
|
}
|
||||||
|
|
@ -20,9 +24,17 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
downloadDao.update(item)
|
downloadDao.update(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDownloadsByWorkID(workID: Int) : List<DownloadItem>{
|
fun getDownloadByWorkID(workID: Int) : DownloadItem{
|
||||||
return downloadDao.getDownloadsByWorkId(workID)
|
return downloadDao.getDownloadByWorkId(workID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getQueuedDownloads() : List<DownloadItem>{
|
||||||
|
return downloadDao.getQueuedDownloads()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setDownloadStatus(item: DownloadItem, status: status){
|
||||||
|
item.status = status.toString()
|
||||||
|
update(item);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
private var downloadCard: SwitchPreferenceCompat? = null
|
private var downloadCard: SwitchPreferenceCompat? = null
|
||||||
private var apiKey: EditTextPreference? = null
|
private var apiKey: EditTextPreference? = null
|
||||||
private var concurrentFragments: SeekBarPreference? = null
|
private var concurrentFragments: SeekBarPreference? = null
|
||||||
|
private var concurrentDownloads: SeekBarPreference? = null
|
||||||
private var limitRate: EditTextPreference? = null
|
private var limitRate: EditTextPreference? = null
|
||||||
private var aria2: SwitchPreferenceCompat? = null
|
private var aria2: SwitchPreferenceCompat? = null
|
||||||
private var sponsorblockFilters: MultiSelectListPreference? = null
|
private var sponsorblockFilters: MultiSelectListPreference? = null
|
||||||
|
|
@ -55,6 +56,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
downloadCard = findPreference("download_card")
|
downloadCard = findPreference("download_card")
|
||||||
apiKey = findPreference("api_key")
|
apiKey = findPreference("api_key")
|
||||||
concurrentFragments = findPreference("concurrent_fragments")
|
concurrentFragments = findPreference("concurrent_fragments")
|
||||||
|
concurrentDownloads = findPreference("concurrent_downloads")
|
||||||
limitRate = findPreference("limit_rate")
|
limitRate = findPreference("limit_rate")
|
||||||
aria2 = findPreference("aria2")
|
aria2 = findPreference("aria2")
|
||||||
sponsorblockFilters = findPreference("sponsorblock_filter")
|
sponsorblockFilters = findPreference("sponsorblock_filter")
|
||||||
|
|
@ -83,6 +85,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
editor.putBoolean("download_card", downloadCard!!.isChecked)
|
editor.putBoolean("download_card", downloadCard!!.isChecked)
|
||||||
editor.putString("api_key", apiKey!!.text)
|
editor.putString("api_key", apiKey!!.text)
|
||||||
editor.putInt("concurrent_fragments", concurrentFragments!!.value)
|
editor.putInt("concurrent_fragments", concurrentFragments!!.value)
|
||||||
|
editor.putInt("concurrent_downloads", concurrentDownloads!!.value)
|
||||||
editor.putString("limit_rate", limitRate!!.text)
|
editor.putString("limit_rate", limitRate!!.text)
|
||||||
editor.putBoolean("aria2", aria2!!.isChecked)
|
editor.putBoolean("aria2", aria2!!.isChecked)
|
||||||
editor.putStringSet("sponsorblock_filters", sponsorblockFilters!!.values)
|
editor.putStringSet("sponsorblock_filters", sponsorblockFilters!!.values)
|
||||||
|
|
@ -159,6 +162,13 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
editor.apply()
|
editor.apply()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
concurrentDownloads!!.onPreferenceChangeListener =
|
||||||
|
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||||
|
val value = newValue.toString().toInt()
|
||||||
|
editor.putInt("concurrent_downloads", value)
|
||||||
|
editor.apply()
|
||||||
|
true
|
||||||
|
}
|
||||||
limitRate!!.onPreferenceChangeListener =
|
limitRate!!.onPreferenceChangeListener =
|
||||||
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
|
||||||
editor.putString("limit_rate", newValue.toString())
|
editor.putString("limit_rate", newValue.toString())
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,21 @@ import android.os.SystemClock
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.work.CoroutineWorker
|
|
||||||
import androidx.work.ForegroundInfo
|
import androidx.work.ForegroundInfo
|
||||||
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.deniscerri.ytdlnis.BuildConfig
|
import com.deniscerri.ytdlnis.BuildConfig
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
|
||||||
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
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.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
import com.yausername.youtubedl_android.YoutubeDLRequest
|
import com.yausername.youtubedl_android.YoutubeDLRequest
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
|
@ -31,8 +31,8 @@ import java.util.regex.Pattern
|
||||||
class DownloadWorker(
|
class DownloadWorker(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
workerParams: WorkerParameters
|
workerParams: WorkerParameters
|
||||||
) : CoroutineWorker(context, workerParams) {
|
) : Worker(context, workerParams) {
|
||||||
override suspend fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
workID = inputData.getInt("workID", SystemClock.uptimeMillis().toInt())
|
workID = inputData.getInt("workID", SystemClock.uptimeMillis().toInt())
|
||||||
val notificationUtil = NotificationUtil(context)
|
val notificationUtil = NotificationUtil(context)
|
||||||
val dbManager = DBManager.getInstance(context)
|
val dbManager = DBManager.getInstance(context)
|
||||||
|
|
@ -41,183 +41,182 @@ class DownloadWorker(
|
||||||
val commandTemplateDao = dbManager.commandTemplateDao
|
val commandTemplateDao = dbManager.commandTemplateDao
|
||||||
val historyDao = dbManager.historyDao
|
val historyDao = dbManager.historyDao
|
||||||
|
|
||||||
queue = repository.getDownloadsByWorkID(workID) as MutableList<DownloadItem>
|
val downloadItem = repository.getDownloadByWorkID(workID)
|
||||||
|
runBlocking{
|
||||||
|
repository.setDownloadStatus(downloadItem, DownloadRepository.status.Active)
|
||||||
|
}
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
||||||
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, queue[0].title, workID, NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
|
val notification = notificationUtil.createDownloadServiceNotification(pendingIntent, downloadItem.title, workID, NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID)
|
||||||
val foregroundInfo = ForegroundInfo(workID, notification)
|
val foregroundInfo = ForegroundInfo(workID, notification)
|
||||||
setForeground(foregroundInfo)
|
setForegroundAsync(foregroundInfo)
|
||||||
|
|
||||||
while (queue.isNotEmpty()){
|
|
||||||
val item = dao.getDownloadById(queue[0].id!!)
|
|
||||||
queue.removeFirst()
|
|
||||||
val url = item.url
|
|
||||||
val request = YoutubeDLRequest(url)
|
|
||||||
val type = item.type
|
|
||||||
val downloadLocation = item.downloadPath
|
|
||||||
|
|
||||||
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${item.title}##${item.type}""")
|
val url = downloadItem.url
|
||||||
when(type){
|
val request = YoutubeDLRequest(url)
|
||||||
"audio" -> tempFolder.append("##${item.audioQualityId}")
|
val type = downloadItem.type
|
||||||
"video" -> tempFolder.append("##${item.videoQualityId}")
|
val downloadLocation = downloadItem.downloadPath
|
||||||
"command" -> tempFolder.append("##${item.customTemplateId}")
|
|
||||||
|
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
|
||||||
|
when(type){
|
||||||
|
"audio" -> tempFolder.append("##${downloadItem.audioQualityId}")
|
||||||
|
"video" -> tempFolder.append("##${downloadItem.videoQualityId}")
|
||||||
|
"command" -> tempFolder.append("##${downloadItem.customTemplateId}")
|
||||||
|
}
|
||||||
|
var tempFileDir = File(tempFolder.toString())
|
||||||
|
tempFileDir.delete()
|
||||||
|
tempFileDir.mkdir()
|
||||||
|
|
||||||
|
val sharedPreferences = context.getSharedPreferences("root_preferences",
|
||||||
|
Service.MODE_PRIVATE
|
||||||
|
)
|
||||||
|
val aria2 = sharedPreferences.getBoolean("aria2", false)
|
||||||
|
if (aria2) {
|
||||||
|
request.addOption("--downloader", "libaria2c.so")
|
||||||
|
request.addOption("--external-downloader-args", "aria2c:\"--summary-interval=1\"")
|
||||||
|
} else {
|
||||||
|
val concurrentFragments = sharedPreferences.getInt("concurrent_fragments", 1)
|
||||||
|
if (concurrentFragments > 1) request.addOption("-N", concurrentFragments)
|
||||||
|
}
|
||||||
|
val limitRate = sharedPreferences.getString("limit_rate", "")
|
||||||
|
if (limitRate != "") request.addOption("-r", limitRate!!)
|
||||||
|
val writeThumbnail = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||||
|
if (writeThumbnail) {
|
||||||
|
request.addOption("--write-thumbnail")
|
||||||
|
request.addOption("--convert-thumbnails", "png")
|
||||||
|
}
|
||||||
|
request.addOption("--no-mtime")
|
||||||
|
val sponsorBlockFilters = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
||||||
|
if (sponsorBlockFilters!!.isNotEmpty()) {
|
||||||
|
val filters = java.lang.String.join(",", sponsorBlockFilters)
|
||||||
|
request.addOption("--sponsorblock-remove", filters)
|
||||||
|
}
|
||||||
|
|
||||||
|
when(type){
|
||||||
|
"audio" -> {
|
||||||
|
request.addOption("-x")
|
||||||
|
var audioQualityId : String = downloadItem.audioQualityId
|
||||||
|
if (audioQualityId == "0") audioQualityId = "ba"
|
||||||
|
var format = downloadItem.audioFormat
|
||||||
|
if (format.isEmpty()){
|
||||||
|
format = sharedPreferences.getString("audio_format", "")!!
|
||||||
|
}
|
||||||
|
request.addOption("-f", audioQualityId)
|
||||||
|
request.addOption("--audio-format", format)
|
||||||
|
request.addOption("--embed-metadata")
|
||||||
|
|
||||||
|
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||||
|
if (embedThumb) {
|
||||||
|
request.addOption("--embed-thumbnail")
|
||||||
|
request.addOption("--convert-thumbnails", "png")
|
||||||
|
try {
|
||||||
|
val config = File(context.cacheDir, "config" + downloadItem.title + "##" + downloadItem.audioQualityId + ".txt")
|
||||||
|
val configData =
|
||||||
|
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||||
|
config.writeText(configData)
|
||||||
|
request.addOption("--config", config.absolutePath)
|
||||||
|
} catch (ignored: Exception) {}
|
||||||
|
}
|
||||||
|
request.addOption("--parse-metadata", "%(release_year,upload_date)s:%(meta_date)s")
|
||||||
|
request.addCommands(listOf("--replace-in-metadata", "title", ".*.", downloadItem.title))
|
||||||
|
request.addCommands(listOf("--replace-in-metadata", "uploader", ".*.", downloadItem.author))
|
||||||
|
|
||||||
|
if (downloadItem.playlistTitle.isNotEmpty()) {
|
||||||
|
request.addOption("--parse-metadata", "%(album,playlist,title)s:%(meta_album)s")
|
||||||
|
request.addOption("--parse-metadata", "%(track_number,playlist_index)d:%(meta_track)s")
|
||||||
|
} else {
|
||||||
|
request.addOption("--parse-metadata", "%(album,title)s:%(meta_album)s")
|
||||||
|
}
|
||||||
|
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
||||||
}
|
}
|
||||||
var tempFileDir = File(tempFolder.toString())
|
"video" -> {
|
||||||
tempFileDir.delete()
|
if (downloadLocation == context.getString(R.string.video_path)){
|
||||||
tempFileDir.mkdir()
|
tempFileDir = File(context.getString(R.string.video_path))
|
||||||
|
}
|
||||||
|
|
||||||
val sharedPreferences = context.getSharedPreferences("root_preferences",
|
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||||
Service.MODE_PRIVATE
|
if (addChapters) {
|
||||||
)
|
request.addOption("--sponsorblock-mark", "all")
|
||||||
val aria2 = sharedPreferences.getBoolean("aria2", false)
|
}
|
||||||
if (aria2) {
|
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
||||||
request.addOption("--downloader", "libaria2c.so")
|
if (embedSubs) {
|
||||||
request.addOption("--external-downloader-args", "aria2c:\"--summary-interval=1\"")
|
request.addOption("--embed-subs", "")
|
||||||
} else {
|
}
|
||||||
val concurrentFragments = sharedPreferences.getInt("concurrent_fragments", 1)
|
var videoQualityId = downloadItem.videoQualityId
|
||||||
if (concurrentFragments > 1) request.addOption("-N", concurrentFragments)
|
val audioQualityId = downloadItem.audioQualityId
|
||||||
}
|
if (videoQualityId.isEmpty()) videoQualityId = "bestvideo"
|
||||||
val limitRate = sharedPreferences.getString("limit_rate", "")
|
val formatArgument = StringBuilder(videoQualityId)
|
||||||
if (limitRate != "") request.addOption("-r", limitRate!!)
|
if (videoQualityId != "worst"){
|
||||||
val writeThumbnail = sharedPreferences.getBoolean("write_thumbnail", false)
|
if (audioQualityId != "0") formatArgument.append("+", audioQualityId, "/best")
|
||||||
if (writeThumbnail) {
|
}
|
||||||
request.addOption("--write-thumbnail")
|
request.addOption("-f", formatArgument.toString())
|
||||||
request.addOption("--convert-thumbnails", "png")
|
var format = downloadItem.videoFormat
|
||||||
}
|
if (format.isNotEmpty()) {
|
||||||
request.addOption("--no-mtime")
|
format = sharedPreferences.getString("video_format", "")!!
|
||||||
val sponsorBlockFilters = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
if (format != "DEFAULT") request.addOption("--merge-output-format", format)
|
||||||
if (sponsorBlockFilters!!.isNotEmpty()) {
|
}
|
||||||
val filters = java.lang.String.join(",", sponsorBlockFilters)
|
|
||||||
request.addOption("--sponsorblock-remove", filters)
|
|
||||||
}
|
|
||||||
|
|
||||||
when(type){
|
|
||||||
"audio" -> {
|
|
||||||
request.addOption("-x")
|
|
||||||
var audioQualityId : String = item.audioQualityId
|
|
||||||
if (audioQualityId == "0") audioQualityId = "ba"
|
|
||||||
var format = item.audioFormat
|
|
||||||
if (format.isEmpty()){
|
|
||||||
format = sharedPreferences.getString("audio_format", "")!!
|
|
||||||
}
|
|
||||||
request.addOption("-f", audioQualityId)
|
|
||||||
request.addOption("--audio-format", format)
|
|
||||||
request.addOption("--embed-metadata")
|
|
||||||
|
|
||||||
|
if (format != "webm") {
|
||||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
||||||
if (embedThumb) {
|
if (embedThumb) {
|
||||||
request.addOption("--embed-thumbnail")
|
request.addOption("--embed-thumbnail")
|
||||||
request.addOption("--convert-thumbnails", "png")
|
|
||||||
try {
|
|
||||||
val config = File(context.cacheDir, "config" + item.title + "##" + item.audioQualityId + ".txt")
|
|
||||||
val configData =
|
|
||||||
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
|
||||||
config.writeText(configData)
|
|
||||||
request.addOption("--config", config.absolutePath)
|
|
||||||
} catch (ignored: Exception) {}
|
|
||||||
}
|
|
||||||
request.addOption("--parse-metadata", "%(release_year,upload_date)s:%(meta_date)s")
|
|
||||||
request.addCommands(listOf("--replace-in-metadata", "title", ".*.", item.title))
|
|
||||||
request.addCommands(listOf("--replace-in-metadata", "uploader", ".*.", item.author))
|
|
||||||
|
|
||||||
if (item.playlistTitle.isNotEmpty()) {
|
|
||||||
request.addOption("--parse-metadata", "%(album,playlist,title)s:%(meta_album)s")
|
|
||||||
request.addOption("--parse-metadata", "%(track_number,playlist_index)d:%(meta_track)s")
|
|
||||||
} else {
|
|
||||||
request.addOption("--parse-metadata", "%(album,title)s:%(meta_album)s")
|
|
||||||
}
|
|
||||||
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
|
||||||
}
|
|
||||||
"video" -> {
|
|
||||||
if (downloadLocation == context.getString(R.string.video_path)){
|
|
||||||
tempFileDir = File(context.getString(R.string.video_path))
|
|
||||||
}
|
|
||||||
|
|
||||||
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
|
||||||
if (addChapters) {
|
|
||||||
request.addOption("--sponsorblock-mark", "all")
|
|
||||||
}
|
|
||||||
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
|
||||||
if (embedSubs) {
|
|
||||||
request.addOption("--embed-subs", "")
|
|
||||||
}
|
|
||||||
var videoQualityId = item.videoQualityId
|
|
||||||
val audioQualityId = item.audioQualityId
|
|
||||||
if (videoQualityId.isEmpty()) videoQualityId = "bestvideo"
|
|
||||||
val formatArgument = StringBuilder(videoQualityId)
|
|
||||||
if (videoQualityId != "worst"){
|
|
||||||
if (audioQualityId != "0") formatArgument.append("+", audioQualityId, "/best")
|
|
||||||
}
|
|
||||||
request.addOption("-f", formatArgument.toString())
|
|
||||||
var format = item.videoFormat
|
|
||||||
if (format.isNotEmpty()) {
|
|
||||||
format = sharedPreferences.getString("video_format", "")!!
|
|
||||||
if (format != "DEFAULT") request.addOption("--merge-output-format", format)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format != "webm") {
|
|
||||||
val embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false)
|
|
||||||
if (embedThumb) {
|
|
||||||
request.addOption("--embed-thumbnail")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
|
||||||
}
|
|
||||||
"command" -> {
|
|
||||||
val commandRegex = "\"([^\"]*)\"|(\\S+)"
|
|
||||||
val command = commandTemplateDao.getTemplateById(item.customTemplateId)
|
|
||||||
val m = Pattern.compile(commandRegex).matcher(command.content)
|
|
||||||
while (m.find()) {
|
|
||||||
if (m.group(1) != null) {
|
|
||||||
request.addOption(m.group(1)!!)
|
|
||||||
} else {
|
|
||||||
request.addOption(m.group(2)!!)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
request.addOption("-o", tempFileDir.absolutePath + "/%(uploader)s - %(title)s.%(ext)s")
|
||||||
}
|
}
|
||||||
|
"command" -> {
|
||||||
runCatching {
|
val commandRegex = "\"([^\"]*)\"|(\\S+)"
|
||||||
YoutubeDL.getInstance().execute(request, item.id.toString()){ progress, _, line ->
|
val command = commandTemplateDao.getTemplateById(downloadItem.customTemplateId)
|
||||||
setProgressAsync(workDataOf("progress" to progress.toInt()))
|
val m = Pattern.compile(commandRegex).matcher(command.content)
|
||||||
var title: String? = context.getString(R.string.download_start)
|
while (m.find()) {
|
||||||
if (queue.isNotEmpty()) {
|
if (m.group(1) != null) {
|
||||||
title = queue[0].title
|
request.addOption(m.group(1)!!)
|
||||||
|
} else {
|
||||||
|
request.addOption(m.group(2)!!)
|
||||||
}
|
}
|
||||||
notificationUtil.updateDownloadNotification(
|
|
||||||
workID,
|
|
||||||
line, progress.toInt(), queue.size, title,
|
|
||||||
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
|
||||||
//move file from internal to set download directory
|
|
||||||
moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
|
|
||||||
setProgressAsync(workDataOf("progress" to progress))
|
|
||||||
}
|
|
||||||
//put download in history
|
|
||||||
val incognito = sharedPreferences.getBoolean("incognito", false)
|
|
||||||
if (!incognito) {
|
|
||||||
val unixtime = System.currentTimeMillis() / 1000
|
|
||||||
val historyItem = HistoryItem(item.url, item.title, item.author, item.duration, item.thumb, item.type, unixtime, item.downloadPath, item.website)
|
|
||||||
historyDao.insert(historyItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
}.onFailure {
|
|
||||||
tempFileDir.delete()
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
|
|
||||||
Log.e(DownloadWorker.TAG, context.getString(R.string.failed_download), it)
|
|
||||||
}
|
|
||||||
notificationUtil.updateDownloadNotification(
|
|
||||||
workID,
|
|
||||||
context.getString(R.string.failed_download), 0, 0, item.title,
|
|
||||||
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
|
||||||
)
|
|
||||||
return Result.failure()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line ->
|
||||||
|
setProgressAsync(workDataOf("progress" to progress.toInt()))
|
||||||
|
val title: String = downloadItem.title
|
||||||
|
val queue = dao.getQueuedDownloads()
|
||||||
|
notificationUtil.updateDownloadNotification(
|
||||||
|
workID,
|
||||||
|
line, progress.toInt(), queue.size, title,
|
||||||
|
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.onSuccess {
|
||||||
|
//move file from internal to set download directory
|
||||||
|
moveFile(tempFileDir.absoluteFile, downloadLocation){ progress ->
|
||||||
|
setProgressAsync(workDataOf("progress" to progress))
|
||||||
|
}
|
||||||
|
//put download in history
|
||||||
|
val incognito = sharedPreferences.getBoolean("incognito", false)
|
||||||
|
if (!incognito) {
|
||||||
|
val unixtime = System.currentTimeMillis() / 1000
|
||||||
|
val historyItem = HistoryItem(downloadItem.url, downloadItem.title, downloadItem.author, downloadItem.duration, downloadItem.thumb, downloadItem.type, unixtime, downloadItem.downloadPath, downloadItem.website)
|
||||||
|
runBlocking {
|
||||||
|
historyDao.insert(historyItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
tempFileDir.delete()
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
|
||||||
|
Log.e(TAG, context.getString(R.string.failed_download), it)
|
||||||
|
}
|
||||||
|
notificationUtil.updateDownloadNotification(
|
||||||
|
workID,
|
||||||
|
context.getString(R.string.failed_download), 0, 0, downloadItem.title,
|
||||||
|
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
|
||||||
|
)
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +246,6 @@ class DownloadWorker(
|
||||||
companion object {
|
companion object {
|
||||||
var workID: Int = 0
|
var workID: Int = 0
|
||||||
const val TAG = "DownloadWorker"
|
const val TAG = "DownloadWorker"
|
||||||
lateinit var queue: MutableList<DownloadItem>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
6
app/src/main/res/drawable/ic_concurrent_downloads.xml
Normal file
6
app/src/main/res/drawable/ic_concurrent_downloads.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<vector android:height="24dp"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?android:colorAccent" android:pathData="M18,6.41l-1.41,-1.41l-4.59,4.58l-4.59,-4.58l-1.41,1.41l6,6z"/>
|
||||||
|
<path android:fillColor="?android:colorAccent" android:pathData="M18,13l-1.41,-1.41l-4.59,4.58l-4.59,-4.58l-1.41,1.41l6,6z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -165,7 +165,4 @@
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<include layout="@layout/home_download_all_bottom_sheet"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout android:id="@+id/history_element_bottom_sheet"
|
|
||||||
style="@style/Widget.Material3.BottomSheet"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="30dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:baselineAligned="false">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/title_textinput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/title"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/author_textinput"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/author"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/audio_format"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/audio_format">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/audio_format_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/music_formats"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -37,7 +38,6 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -87,33 +87,10 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/download_multiple_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent" />
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
|
||||||
android:id="@+id/bottomsheet_audio_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:icon="@drawable/ic_music"
|
|
||||||
android:text="@string/audio" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
|
||||||
android:id="@+id/bottomsheet_video_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/video"
|
|
||||||
app:icon="@drawable/ic_video"
|
|
||||||
android:autoLink="all"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
163
app/src/main/res/layout/home_download_multiple_card.xml
Normal file
163
app/src/main/res/layout/home_download_multiple_card.xml
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/result_card_constraintLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/result_relative_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintDimensionRatio="H,3:1"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/download_multiple_card_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:cardCornerRadius="10dp"
|
||||||
|
app:cardElevation="10dp"
|
||||||
|
app:cardMaxElevation="12dp"
|
||||||
|
app:cardPreventCornerOverlap="true"
|
||||||
|
android:checkable="true"
|
||||||
|
app:strokeWidth="0dp"
|
||||||
|
android:layout_margin="10dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/result_image_view"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:dividerPadding="5dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.8"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/result_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:textSize="17sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="2"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowColor="@color/black" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/author"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="1.5"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowColor="@color/black" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
|
android:id="@+id/download_type"
|
||||||
|
android:layout_width="55dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
app:cornerRadius="10dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/format"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="1.5"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowColor="@color/black" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/quality"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="1.5"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowColor="@color/black" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/filesize"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:shadowRadius="1.5"
|
||||||
|
android:shadowDx="4"
|
||||||
|
android:shadowDy="4"
|
||||||
|
android:shadowColor="@color/black" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
60
app/src/main/res/layout/home_download_settings.xml
Normal file
60
app/src/main/res/layout/home_download_settings.xml
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout android:id="@+id/history_element_bottom_sheet"
|
||||||
|
style="@style/Widget.Material3.BottomSheet"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="20dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bottom_sheet_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:textSize="25sp"
|
||||||
|
android:textColor="?attr/colorOnSurface"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/configure_download" />
|
||||||
|
|
||||||
|
<include layout="@layout/home_download_settings_components" />
|
||||||
|
|
||||||
|
<View style="@style/Divider.Horizontal"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
||||||
|
android:id="@+id/bottomsheet_schedule_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:icon="@drawable/ic_cancel"
|
||||||
|
android:text="@string/cancel" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:id="@+id/bottomsheet_download_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/ok"
|
||||||
|
app:icon="@drawable/ic_check"
|
||||||
|
android:autoLink="all"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
242
app/src/main/res/layout/home_download_settings_components.xml
Normal file
242
app/src/main/res/layout/home_download_settings_components.xml
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/title_textinput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
android:hint="@string/title"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/author_textinput"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="45"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
android:hint="@string/author"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/audio_format"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:layout_weight="45"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/audio_format">
|
||||||
|
|
||||||
|
<AutoCompleteTextView
|
||||||
|
android:id="@+id/audio_format_textview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="none"
|
||||||
|
app:simpleItems="@array/music_formats"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/outputPath_textinput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
android:hint="@string/save_dir"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:selectionRequired="true"
|
||||||
|
app:singleLine="true"
|
||||||
|
app:singleSelection="true">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/audioChip"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checkable="true"
|
||||||
|
app:checkedIcon="@drawable/ic_check"
|
||||||
|
android:text="@string/audio"
|
||||||
|
app:chipIcon="@drawable/ic_music" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/videoChip"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/video"
|
||||||
|
android:checkable="true"
|
||||||
|
app:checkedIcon="@drawable/ic_check"
|
||||||
|
app:chipIcon="@drawable/ic_video" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/commandChip"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/run_command"
|
||||||
|
android:checkable="true"
|
||||||
|
app:checkedIcon="@drawable/ic_check"
|
||||||
|
app:chipIcon="@drawable/ic_baseline_keyboard_arrow_right_24" />
|
||||||
|
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/adjust_commands"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/adjust_templates" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/commands_chip_group"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:selectionRequired="false"
|
||||||
|
app:singleLine="true"
|
||||||
|
app:singleSelection="false">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/newTemplate"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/new_template"
|
||||||
|
app:chipIcon="@drawable/ic_plus" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/editSelected"
|
||||||
|
style="@style/Widget.Material3.Chip.Assist"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/edit_selected"
|
||||||
|
app:chipIcon="@drawable/ic_edit" />
|
||||||
|
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/adjust_video"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:paddingTop="5dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/adjust_video" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/chipGroup"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
app:singleLine="true"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/embed_subtitles"
|
||||||
|
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/embed_subtitles"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/add_chapters"
|
||||||
|
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/add_chapter"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/save_thumbnail"
|
||||||
|
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/save_thumb"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/remove_audio"
|
||||||
|
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/remove_audio"/>
|
||||||
|
|
||||||
|
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -23,242 +23,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/download" />
|
android:text="@string/download" />
|
||||||
|
|
||||||
<TextView
|
<include layout="@layout/home_download_settings_components" />
|
||||||
android:id="@+id/bottom_sheet_author"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/configure_download" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/title_textinput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="15dp"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/title"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/author_textinput"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/author"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/audio_format"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/audio_format">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/audio_format_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/music_formats"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/outputPath_textinput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/save_dir"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:selectionRequired="true"
|
|
||||||
app:singleLine="true"
|
|
||||||
app:singleSelection="true">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/audioChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
android:text="@string/audio"
|
|
||||||
app:chipIcon="@drawable/ic_music" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/videoChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/video"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
app:chipIcon="@drawable/ic_video" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/commandChip"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/run_command"
|
|
||||||
android:checkable="true"
|
|
||||||
app:checkedIcon="@drawable/ic_check"
|
|
||||||
app:chipIcon="@drawable/ic_baseline_keyboard_arrow_right_24" />
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/adjust_commands"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/adjust_templates" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:id="@+id/commands_chip_group"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:selectionRequired="false"
|
|
||||||
app:singleLine="true"
|
|
||||||
app:singleSelection="false">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/newTemplate"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/new_template"
|
|
||||||
app:chipIcon="@drawable/ic_plus" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/editSelected"
|
|
||||||
style="@style/Widget.Material3.Chip.Assist"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/edit_selected"
|
|
||||||
app:chipIcon="@drawable/ic_edit" />
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/adjust_video"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/adjust_video" />
|
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:id="@+id/chipGroup"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
app:singleLine="true"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/embed_subtitles"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/embed_subtitles"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/add_chapters"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/add_chapter"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/save_thumbnail"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/save_thumb"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/remove_audio"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/remove_audio"/>
|
|
||||||
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View style="@style/Divider.Horizontal"/>
|
<View style="@style/Divider.Horizontal"/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout android:id="@+id/history_element_bottom_sheet"
|
|
||||||
style="@style/Widget.Material3.BottomSheet"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/bottom_sheet_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:textSize="25sp"
|
|
||||||
android:textColor="?attr/colorOnSurface"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/download_video" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/bottom_sheet_author"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:paddingTop="5dp"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/configure_download" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="30dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:baselineAligned="false">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/title_textinput"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/title"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/video_format"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/video_format">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/video_format_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/video_formats"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/video_quality"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/video_quality">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/video_quality_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/video_quality"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="20dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<HorizontalScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:id="@+id/chipGroup"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
app:singleLine="true"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/embed_subtitles"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/embed_subtitles"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/add_chapters"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/add_chapter"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/save_thumbnail"
|
|
||||||
style="@style/Widget.Material3.Chip.Filter.Elevated"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:checked="false"
|
|
||||||
android:text="@string/save_thumb"/>
|
|
||||||
|
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
|
|
||||||
</HorizontalScrollView>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
|
||||||
android:id="@+id/bottomsheet_cancel_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:icon="@drawable/ic_cancel"
|
|
||||||
android:text="@string/cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
|
||||||
android:id="@+id/bottomsheet_download_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/download"
|
|
||||||
app:icon="@drawable/ic_down"
|
|
||||||
android:autoLink="all"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">YTDLnis</string>
|
|
||||||
<string name="search">Ara</string>
|
<string name="search">Ara</string>
|
||||||
<string name="remove_all"> Tümünü Kaldır</string>
|
<string name="remove_all"> Tümünü Kaldır</string>
|
||||||
<string name="remove_results"> Clear Results</string>
|
<string name="remove_results"> Clear Results</string>
|
||||||
|
|
@ -65,9 +64,6 @@
|
||||||
<string name="choose_range_desc">Çalma listesinden indirmek için bir aralık seçin (her şeyi indirmemek için).</string>
|
<string name="choose_range_desc">Çalma listesinden indirmek için bir aralık seçin (her şeyi indirmemek için).</string>
|
||||||
<string name="last_cant_be_smaller_than_first">Son dizin ilkinden daha küçük olamaz.</string>
|
<string name="last_cant_be_smaller_than_first">Son dizin ilkinden daha küçük olamaz.</string>
|
||||||
<string name="first_cant_be_larger_than_last">İlk dizin son dizinden büyük olamaz.</string>
|
<string name="first_cant_be_larger_than_last">İlk dizin son dizinden büyük olamaz.</string>
|
||||||
<string name="music_path" translatable="false">/storage/emulated/0/Download</string>
|
|
||||||
<string name="video_path" translatable="false">/storage/emulated/0/Download</string>
|
|
||||||
<string name="command_path" translatable="false">/storage/emulated/0/Download</string>
|
|
||||||
<string name="concurrent_fragments_summary">Eşzamanlı olarak indirilecek DASH/HLS yerel video parçalarının sayısı</string>
|
<string name="concurrent_fragments_summary">Eşzamanlı olarak indirilecek DASH/HLS yerel video parçalarının sayısı</string>
|
||||||
<string name="concurrent_fragments">Eşzamanlı Parçalar</string>
|
<string name="concurrent_fragments">Eşzamanlı Parçalar</string>
|
||||||
<string name="downloading">İndirme</string>
|
<string name="downloading">İndirme</string>
|
||||||
|
|
@ -110,7 +106,6 @@
|
||||||
<string name="newest_first">En yeni</string>
|
<string name="newest_first">En yeni</string>
|
||||||
<string name="oldest_first">En eski</string>
|
<string name="oldest_first">En eski</string>
|
||||||
<item type="id" name="cancelDownload"/>
|
<item type="id" name="cancelDownload"/>
|
||||||
<string name="trendingPlaylist" translatable="false">ytdlnis-TRENDING</string>
|
|
||||||
<string name="currently_downloading">İndiriliyor</string>
|
<string name="currently_downloading">İndiriliyor</string>
|
||||||
<string name="remove_downloading">İndirmeleri İptal Et</string>
|
<string name="remove_downloading">İndirmeleri İptal Et</string>
|
||||||
<string name="confirm_delete_downloading_desc">İndirilmekte olan tüm öğeleri kaldırın ve indirme hizmetini durdurun?</string>
|
<string name="confirm_delete_downloading_desc">İndirilmekte olan tüm öğeleri kaldırın ve indirme hizmetini durdurun?</string>
|
||||||
|
|
|
||||||
|
|
@ -158,4 +158,6 @@
|
||||||
<string name="adjust_video">Adjust video</string>
|
<string name="adjust_video">Adjust video</string>
|
||||||
<string name="remove_audio">Remove Audio</string>
|
<string name="remove_audio">Remove Audio</string>
|
||||||
<string name="schedule">Schedule</string>
|
<string name="schedule">Schedule</string>
|
||||||
|
<string name="concurrent_downloads">Concurrent Downloads</string>
|
||||||
|
<string name="concurrent_downloads_summary">Number of downloads executing at the same time</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -56,6 +56,17 @@
|
||||||
app:summary="@string/concurrent_fragments_summary"
|
app:summary="@string/concurrent_fragments_summary"
|
||||||
app:title="@string/concurrent_fragments" />
|
app:title="@string/concurrent_fragments" />
|
||||||
|
|
||||||
|
<SeekBarPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:icon="@drawable/ic_concurrent_downloads"
|
||||||
|
android:max="5"
|
||||||
|
app:key="concurrent_downloads"
|
||||||
|
app:min="1"
|
||||||
|
app:showSeekBarValue="true"
|
||||||
|
android:dependency="aria2"
|
||||||
|
app:summary="@string/concurrent_downloads_summary"
|
||||||
|
app:title="@string/concurrent_downloads" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:icon="@drawable/ic_down"
|
android:icon="@drawable/ic_down"
|
||||||
app:key="limit_rate"
|
app:key="limit_rate"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue