CHANGELOG
made from and to textboxes wider in the cut video screen added search engines in the search view removed filename template override if the user leaves it empty. Now it follows the yt-dlp default fixed app crashing when its tablet added drag handle to scrolling content added pause functionality made video player faster to load for youtube videos
This commit is contained in:
parent
0cacff6e9f
commit
6dc25bab9a
67 changed files with 883 additions and 435 deletions
|
|
@ -10,7 +10,7 @@ def properties = new Properties()
|
||||||
def versionMajor = 1
|
def versionMajor = 1
|
||||||
def versionMinor = 6
|
def versionMinor = 6
|
||||||
def versionPatch = 3
|
def versionPatch = 3
|
||||||
def versionBuild = 9 // bump for dogfood builds, public betas, etc.
|
def versionBuild = 10 // bump for dogfood builds, public betas, etc.
|
||||||
def versionExt = ""
|
def versionExt = ""
|
||||||
|
|
||||||
if (versionBuild > 0){
|
if (versionBuild > 0){
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,8 @@ class MainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(navigationView as NavigationView).getHeaderView(0).findViewById<TextView>(R.id.title).text = ThemeUtil.getStyledAppName(this)
|
||||||
}
|
}
|
||||||
cookieViewModel.updateCookiesFile()
|
cookieViewModel.updateCookiesFile()
|
||||||
val intent = intent
|
val intent = intent
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
|
@ -17,6 +18,7 @@ import androidx.recyclerview.widget.ListAdapter
|
||||||
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.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
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
|
||||||
|
|
@ -56,12 +58,13 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
val card = holder.cardView
|
val card = holder.cardView
|
||||||
|
card.tag = "${item!!.id}##card"
|
||||||
val uiHandler = Handler(Looper.getMainLooper())
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
val thumbnail = card.findViewById<ImageView>(R.id.image_view)
|
val thumbnail = card.findViewById<ImageView>(R.id.image_view)
|
||||||
|
|
||||||
// THUMBNAIL ----------------------------------
|
// THUMBNAIL ----------------------------------
|
||||||
if (!sharedPreferences.getStringSet("hide_thumbnails", emptySet())!!.contains("queue")){
|
if (!sharedPreferences.getStringSet("hide_thumbnails", emptySet())!!.contains("queue")){
|
||||||
val imageURL = item!!.thumb
|
val imageURL = item.thumb
|
||||||
if (imageURL.isNotEmpty()) {
|
if (imageURL.isNotEmpty()) {
|
||||||
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -74,7 +77,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
|
|
||||||
// PROGRESS BAR ----------------------------------------------------
|
// PROGRESS BAR ----------------------------------------------------
|
||||||
val progressBar = card.findViewById<LinearProgressIndicator>(R.id.progress)
|
val progressBar = card.findViewById<LinearProgressIndicator>(R.id.progress)
|
||||||
progressBar.tag = "${item!!.id}##progress"
|
progressBar.tag = "${item.id}##progress"
|
||||||
progressBar.progress = 0
|
progressBar.progress = 0
|
||||||
progressBar.isIndeterminate = true
|
progressBar.isIndeterminate = true
|
||||||
|
|
||||||
|
|
@ -105,17 +108,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
val formatDetailsChip = card.findViewById<Chip>(R.id.format_note)
|
val formatDetailsChip = card.findViewById<Chip>(R.id.format_note)
|
||||||
val formatDetailsText = StringBuilder(item.format.format_note.uppercase())
|
val formatDetailsText = StringBuilder(item.format.format_note.uppercase())
|
||||||
|
|
||||||
val codecText =
|
formatDetailsText.append(" \t •\t ${item.container.uppercase().ifEmpty { item.format.container.uppercase() }}")
|
||||||
if (item.format.encoding != "") {
|
|
||||||
item.format.encoding.uppercase()
|
|
||||||
}else if (item.format.vcodec != "none" && item.format.vcodec != ""){
|
|
||||||
item.format.vcodec.uppercase()
|
|
||||||
} else {
|
|
||||||
item.format.acodec.uppercase()
|
|
||||||
}
|
|
||||||
if (codecText != "" && codecText != "none"){
|
|
||||||
formatDetailsText.append(" \t •\t $codecText")
|
|
||||||
}
|
|
||||||
|
|
||||||
val fileSize = FileUtil.convertFileSize(item.format.filesize)
|
val fileSize = FileUtil.convertFileSize(item.format.filesize)
|
||||||
if (fileSize != "?") formatDetailsText.append(" \t •\t $fileSize")
|
if (fileSize != "?") formatDetailsText.append(" \t •\t $fileSize")
|
||||||
|
|
@ -131,19 +124,54 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// CANCEL BUTTON ----------------------------------
|
// PAUSE BUTTON ----------------------------------
|
||||||
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_cancel)
|
val pauseButton = card.findViewById<MaterialButton>(R.id.active_download_pause)
|
||||||
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
if (pauseButton.hasOnClickListeners()) pauseButton.setOnClickListener(null)
|
||||||
|
|
||||||
cancelButton.setOnClickListener {
|
// CANCEL BUTTON ----------------------------------
|
||||||
onItemClickListener.onCancelClick(item.id)
|
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_delete)
|
||||||
|
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
||||||
|
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
||||||
|
|
||||||
|
if (item.status == DownloadRepository.Status.Paused.toString()){
|
||||||
|
progressBar.isIndeterminate = false
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
pauseButton.tag = ActiveDownloadAction.Resume
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
}else{
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
pauseButton.tag = ActiveDownloadAction.Pause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pauseButton.setOnClickListener {
|
||||||
|
if (pauseButton.tag == ActiveDownloadAction.Pause){
|
||||||
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Pause)
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
if (progressBar.progress == 0) progressBar.isIndeterminate = false
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
pauseButton.tag = ActiveDownloadAction.Resume
|
||||||
|
}else{
|
||||||
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAction.Resume)
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
pauseButton.tag = ActiveDownloadAction.Pause
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
interface OnItemClickListener {
|
interface OnItemClickListener {
|
||||||
fun onCancelClick(itemID: Long)
|
fun onCancelClick(itemID: Long)
|
||||||
|
fun onPauseClick(itemID: Long, action: ActiveDownloadAction)
|
||||||
fun onOutputClick(item: DownloadItem)
|
fun onOutputClick(item: DownloadItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class ActiveDownloadAction {
|
||||||
|
Resume, Pause
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
|
||||||
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
||||||
|
|
@ -152,7 +180,7 @@ class ActiveDownloadAdapter(onItemClickListener: OnItemClickListener, activity:
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): 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 && oldItem.status == newItem.status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
|
@ -17,6 +18,7 @@ import androidx.recyclerview.widget.ListAdapter
|
||||||
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.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
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
|
||||||
|
|
@ -86,9 +88,6 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac
|
||||||
}
|
}
|
||||||
itemTitle.text = title.ifEmpty { item.url }
|
itemTitle.text = title.ifEmpty { item.url }
|
||||||
|
|
||||||
val duration = card.findViewById<TextView>(R.id.duration)
|
|
||||||
duration.text = item.duration
|
|
||||||
|
|
||||||
|
|
||||||
val formatDetailsChip = card.findViewById<TextView>(R.id.format_note)
|
val formatDetailsChip = card.findViewById<TextView>(R.id.format_note)
|
||||||
val formatDetailsText = StringBuilder(item.format.format_note.uppercase())
|
val formatDetailsText = StringBuilder(item.format.format_note.uppercase())
|
||||||
|
|
@ -110,12 +109,41 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac
|
||||||
|
|
||||||
formatDetailsChip.text = formatDetailsText
|
formatDetailsChip.text = formatDetailsText
|
||||||
|
|
||||||
// CANCEL BUTTON ----------------------------------
|
// PAUSE BUTTON ----------------------------------
|
||||||
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_cancel)
|
val pauseButton = card.findViewById<MaterialButton>(R.id.active_download_pause)
|
||||||
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
if (pauseButton.hasOnClickListeners()) pauseButton.setOnClickListener(null)
|
||||||
|
|
||||||
cancelButton.setOnClickListener {
|
// CANCEL BUTTON ----------------------------------
|
||||||
onItemClickListener.onCancelClick(item.id)
|
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_delete)
|
||||||
|
if (cancelButton.hasOnClickListeners()) cancelButton.setOnClickListener(null)
|
||||||
|
cancelButton.setOnClickListener {onItemClickListener.onCancelClick(item.id)}
|
||||||
|
|
||||||
|
if (item.status == DownloadRepository.Status.Paused.toString()){
|
||||||
|
progressBar.isIndeterminate = false
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
}else{
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Pause
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseButton.setOnClickListener {
|
||||||
|
if (pauseButton.tag == ActiveDownloadAdapter.ActiveDownloadAction.Pause){
|
||||||
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAdapter.ActiveDownloadAction.Pause)
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
if (progressBar.progress == 0) progressBar.isIndeterminate = false
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume
|
||||||
|
}else{
|
||||||
|
onItemClickListener.onPauseClick(item.id, ActiveDownloadAdapter.ActiveDownloadAction.Resume)
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(activity, R.drawable.exomedia_ic_pause_white)
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Pause
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
card.setOnClickListener {
|
card.setOnClickListener {
|
||||||
|
|
@ -124,9 +152,11 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac
|
||||||
}
|
}
|
||||||
interface OnItemClickListener {
|
interface OnItemClickListener {
|
||||||
fun onCancelClick(itemID: Long)
|
fun onCancelClick(itemID: Long)
|
||||||
|
fun onPauseClick(itemID: Long, action: ActiveDownloadAdapter.ActiveDownloadAction)
|
||||||
fun onCardClick()
|
fun onCardClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
|
||||||
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
||||||
|
|
@ -135,7 +165,7 @@ class ActiveDownloadMinifiedAdapter(onItemClickListener: OnItemClickListener, ac
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
|
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): 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 && oldItem.status == newItem.status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,13 +90,12 @@ class HomeAdapter(onItemClickListener: OnItemClickListener, activity: Activity)
|
||||||
|
|
||||||
// BUTTONS ----------------------------------
|
// BUTTONS ----------------------------------
|
||||||
val videoURL = video.url
|
val videoURL = video.url
|
||||||
val buttonLayout = card.findViewById<LinearLayout>(R.id.download_button_layout)
|
val musicBtn = card.findViewById<MaterialButton>(R.id.download_music)
|
||||||
val musicBtn = buttonLayout.findViewById<MaterialButton>(R.id.download_music)
|
|
||||||
musicBtn.tag = "$videoURL##audio"
|
musicBtn.tag = "$videoURL##audio"
|
||||||
musicBtn.setTag(R.id.cancelDownload, "false")
|
musicBtn.setTag(R.id.cancelDownload, "false")
|
||||||
musicBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, DownloadViewModel.Type.audio) }
|
musicBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, DownloadViewModel.Type.audio) }
|
||||||
musicBtn.setOnLongClickListener{ onItemClickListener.onLongButtonClick(videoURL, DownloadViewModel.Type.audio); true}
|
musicBtn.setOnLongClickListener{ onItemClickListener.onLongButtonClick(videoURL, DownloadViewModel.Type.audio); true}
|
||||||
val videoBtn = buttonLayout.findViewById<MaterialButton>(R.id.download_video)
|
val videoBtn = card.findViewById<MaterialButton>(R.id.download_video)
|
||||||
videoBtn.tag = "$videoURL##video"
|
videoBtn.tag = "$videoURL##video"
|
||||||
videoBtn.setTag(R.id.cancelDownload, "false")
|
videoBtn.setTag(R.id.cancelDownload, "false")
|
||||||
videoBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, DownloadViewModel.Type.video) }
|
videoBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, DownloadViewModel.Type.video) }
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,16 @@ interface DownloadDao {
|
||||||
@Query("SELECT * FROM downloads ORDER BY status")
|
@Query("SELECT * FROM downloads ORDER BY status")
|
||||||
fun getAllDownloads() : Flow<List<DownloadItem>>
|
fun getAllDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'")
|
||||||
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
fun getActiveDownloads() : Flow<List<DownloadItem>>
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM downloads WHERE status='Active'")
|
@Query("SELECT COUNT(*) FROM downloads WHERE status='Active' or status='Paused'")
|
||||||
fun getActiveDownloadsCount() : Flow<Int>
|
fun getActiveDownloadsCount() : Flow<Int>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active'")
|
@Query("SELECT * FROM downloads WHERE status='Active' or status='Paused'")
|
||||||
fun getActiveDownloadsList() : List<DownloadItem>
|
fun getActiveDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Active' or status='Queued'")
|
@Query("SELECT * FROM downloads WHERE status='Active' or status='Queued' or status='Paused'")
|
||||||
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
|
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
|
||||||
|
|
||||||
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
|
||||||
val savedDownloads : Flow<List<DownloadItem>> = downloadDao.getSavedDownloads()
|
val savedDownloads : Flow<List<DownloadItem>> = downloadDao.getSavedDownloads()
|
||||||
|
|
||||||
enum class Status {
|
enum class Status {
|
||||||
Active, Queued, Error, Processing, Cancelled, Saved
|
Active, Paused, Queued, Error, Cancelled, Saved
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun insert(item: DownloadItem) : Long {
|
suspend fun insert(item: DownloadItem) : Long {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.asLiveData
|
import androidx.lifecycle.asLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.anggrayudi.storage.file.dataDirectory
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
import com.deniscerri.ytdlnis.database.models.CookieItem
|
import com.deniscerri.ytdlnis.database.models.CookieItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.CookieRepository
|
import com.deniscerri.ytdlnis.database.repository.CookieRepository
|
||||||
|
|
@ -72,11 +73,11 @@ class CookieViewModel(private val application: Application) : AndroidViewModel(a
|
||||||
flush()
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
var dbPath = "/data/data/com.deniscerri.ytdl/app_webview/Cookies"
|
val dbPath = File("/data/data/com.deniscerri.ytdl/").walkTopDown().find { it.name == "Cookies" }
|
||||||
if (!File(dbPath).exists()) dbPath = "/data/data/com.deniscerri.ytdl/app_webview/Default/Cookies"
|
?: throw Exception("Cookies File not found!")
|
||||||
|
|
||||||
SQLiteDatabase.openDatabase(
|
SQLiteDatabase.openDatabase(
|
||||||
dbPath, null, OPEN_READONLY
|
dbPath.absolutePath, null, OPEN_READONLY
|
||||||
).run {
|
).run {
|
||||||
val projection = arrayOf(
|
val projection = arrayOf(
|
||||||
CookieObject.HOST,
|
CookieObject.HOST,
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,11 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
|
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val container = when(type){
|
||||||
|
Type.audio -> sharedPreferences.getString("audio_format", "")
|
||||||
|
else -> sharedPreferences.getString("video_format", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
val sponsorblock = sharedPreferences.getStringSet("sponsorblock_filters", emptySet())
|
||||||
|
|
||||||
|
|
@ -182,10 +187,10 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
resultItem.duration,
|
resultItem.duration,
|
||||||
type,
|
type,
|
||||||
getFormat(resultItem.formats, type),
|
getFormat(resultItem.formats, type),
|
||||||
sharedPreferences.getString("video_format", "Default")!!,
|
container!!,
|
||||||
"",
|
"",
|
||||||
resultItem.formats,
|
resultItem.formats,
|
||||||
downloadPath!!, resultItem.website, "", resultItem.playlistTitle, audioPreferences, videoPreferences, "", customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0, null
|
downloadPath!!, resultItem.website, "", resultItem.playlistTitle, audioPreferences, videoPreferences, "", customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Queued.toString(), 0, null
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -307,7 +312,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
container,
|
container,
|
||||||
"",
|
"",
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
path, historyItem.website, "", "", audioPreferences, videoPreferences, "", customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0, null
|
path, historyItem.website, "", "", audioPreferences, videoPreferences, "", customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Queued.toString(), 0, null
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -459,7 +464,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
|
||||||
var exists = false
|
var exists = false
|
||||||
|
|
||||||
items.forEach {
|
items.forEach {
|
||||||
it.status = DownloadRepository.Status.Queued.toString()
|
if (it.status != DownloadRepository.Status.Paused.toString()) it.status = DownloadRepository.Status.Queued.toString()
|
||||||
if (activeAndQueuedDownloads.firstOrNull{d ->
|
if (activeAndQueuedDownloads.firstOrNull{d ->
|
||||||
d.id = 0
|
d.id = 0
|
||||||
d.status = DownloadRepository.Status.Queued.toString()
|
d.status = DownloadRepository.Status.Queued.toString()
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,14 @@ package com.deniscerri.ytdlnis.receiver
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
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 kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
class CancelDownloadNotificationReceiver : BroadcastReceiver() {
|
class CancelDownloadNotificationReceiver : BroadcastReceiver() {
|
||||||
override fun onReceive(c: Context, intent: Intent) {
|
override fun onReceive(c: Context, intent: Intent) {
|
||||||
|
|
@ -14,6 +20,14 @@ class CancelDownloadNotificationReceiver : BroadcastReceiver() {
|
||||||
val notificationUtil = NotificationUtil(c)
|
val notificationUtil = NotificationUtil(c)
|
||||||
notificationUtil.cancelDownloadNotification(id)
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
|
|
||||||
|
val dbManager = DBManager.getInstance(c)
|
||||||
|
CoroutineScope(Dispatchers.IO).launch{
|
||||||
|
val item = dbManager.downloadDao.getDownloadById(id.toLong())
|
||||||
|
item.status = DownloadRepository.Status.Cancelled.toString()
|
||||||
|
dbManager.downloadDao.update(item)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,12 @@ import android.app.Activity
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.content.Context.CLIPBOARD_SERVICE
|
import android.content.Context.CLIPBOARD_SERVICE
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Resources.Theme
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.View.*
|
import android.view.View.*
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
|
|
@ -36,7 +34,6 @@ import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
|
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.DownloadMultipleBottomSheetDialog
|
||||||
import com.deniscerri.ytdlnis.ui.downloadcard.ResultCardDetailsDialog
|
import com.deniscerri.ytdlnis.ui.downloadcard.ResultCardDetailsDialog
|
||||||
|
|
@ -137,7 +134,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
searchHistory = view.findViewById(R.id.search_history_scroll_view)
|
searchHistory = view.findViewById(R.id.search_history_scroll_view)
|
||||||
searchHistoryLinearLayout = view.findViewById(R.id.search_history_linear_layout)
|
searchHistoryLinearLayout = view.findViewById(R.id.search_history_linear_layout)
|
||||||
|
|
||||||
materialToolbar!!.title = ThemeUtil.getStyledAppName(requireContext())
|
runCatching { materialToolbar!!.title = ThemeUtil.getStyledAppName(requireContext()) }
|
||||||
|
|
||||||
homeAdapter =
|
homeAdapter =
|
||||||
HomeAdapter(
|
HomeAdapter(
|
||||||
|
|
@ -257,6 +254,30 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, OnClickListene
|
||||||
val queriesInitStartBtn = queriesConstraint.findViewById<MaterialButton>(R.id.init_search_query)
|
val queriesInitStartBtn = queriesConstraint.findViewById<MaterialButton>(R.id.init_search_query)
|
||||||
val isRightToLeft = resources.getBoolean(R.bool.is_right_to_left)
|
val isRightToLeft = resources.getBoolean(R.bool.is_right_to_left)
|
||||||
|
|
||||||
|
val providersChipGroup = searchView!!.findViewById<ChipGroup>(R.id.providers)
|
||||||
|
val providers = resources.getStringArray(R.array.search_engines)
|
||||||
|
val providersValues = resources.getStringArray(R.array.search_engines_values).toMutableList()
|
||||||
|
val currentProvider = sharedPreferences?.getString("search_engine", "ytsearch")
|
||||||
|
|
||||||
|
for(i in providersValues.indices){
|
||||||
|
val provider = providers[i]
|
||||||
|
val providerValue = providersValues[i]
|
||||||
|
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, providersChipGroup, false) as Chip
|
||||||
|
tmp.text = provider
|
||||||
|
tmp.id = i
|
||||||
|
|
||||||
|
if (currentProvider == providerValue) tmp.isChecked = true
|
||||||
|
|
||||||
|
tmp.setOnClickListener {
|
||||||
|
val editor = sharedPreferences?.edit()
|
||||||
|
editor?.putString("search_engine", providerValue)
|
||||||
|
editor?.apply()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
providersChipGroup!!.addView(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
infoUtil = InfoUtil(requireContext())
|
infoUtil = InfoUtil(requireContext())
|
||||||
searchView!!.addTransitionListener { _, _, newState ->
|
searchView!!.addTransitionListener { _, _, newState ->
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.map
|
import androidx.lifecycle.map
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
import androidx.media3.exoplayer.source.MergingMediaSource
|
import androidx.media3.exoplayer.source.MergingMediaSource
|
||||||
|
|
@ -35,6 +34,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.adapter.ActiveDownloadAdapter
|
||||||
import com.deniscerri.ytdlnis.adapter.ActiveDownloadMinifiedAdapter
|
import com.deniscerri.ytdlnis.adapter.ActiveDownloadMinifiedAdapter
|
||||||
import com.deniscerri.ytdlnis.adapter.GenericDownloadAdapter
|
import com.deniscerri.ytdlnis.adapter.GenericDownloadAdapter
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
|
|
@ -68,7 +68,6 @@ import java.util.*
|
||||||
class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogFragment(), GenericDownloadAdapter.OnItemClickListener, ActiveDownloadMinifiedAdapter.OnItemClickListener {
|
class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogFragment(), GenericDownloadAdapter.OnItemClickListener, ActiveDownloadMinifiedAdapter.OnItemClickListener {
|
||||||
private lateinit var infoUtil: InfoUtil
|
private lateinit var infoUtil: InfoUtil
|
||||||
private lateinit var notificationUtil: NotificationUtil
|
private lateinit var notificationUtil: NotificationUtil
|
||||||
private lateinit var player: ExoPlayer
|
|
||||||
private lateinit var videoView: PlayerView
|
private lateinit var videoView: PlayerView
|
||||||
private lateinit var downloadViewModel: DownloadViewModel
|
private lateinit var downloadViewModel: DownloadViewModel
|
||||||
private lateinit var resultViewModel: ResultViewModel
|
private lateinit var resultViewModel: ResultViewModel
|
||||||
|
|
@ -232,9 +231,8 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
videoView = view.findViewById<PlayerView>(R.id.video_view)
|
videoView = view.findViewById(R.id.video_view)
|
||||||
val pause = view.findViewById<MaterialButton>(R.id.pause)
|
val pause = view.findViewById<MaterialButton>(R.id.pause)
|
||||||
val frameLayout = view.findViewById<FrameLayout>(R.id.frame_layout)
|
|
||||||
|
|
||||||
val player = VideoPlayerUtil.buildPlayer(requireContext())
|
val player = VideoPlayerUtil.buildPlayer(requireContext())
|
||||||
videoView.player = player
|
videoView.player = player
|
||||||
|
|
@ -261,7 +259,7 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.removeFirst()
|
if (data.size > 1) data.removeFirst()
|
||||||
|
|
||||||
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
if (data.isEmpty()) throw Exception("No Streaming URL found!")
|
||||||
if (data.size == 2){
|
if (data.size == 2){
|
||||||
|
|
@ -280,7 +278,6 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
player.prepare()
|
player.prepare()
|
||||||
player.play()
|
player.play()
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
frameLayout.visibility = View.GONE
|
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -536,7 +533,24 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
override fun onCancelClick(itemID: Long) {
|
override fun onCancelClick(itemID: Long) {
|
||||||
cancelActiveDownload(itemID)
|
cancelActiveDownload(itemID)
|
||||||
}
|
}
|
||||||
|
override fun onPauseClick(itemID: Long, action: ActiveDownloadAdapter.ActiveDownloadAction) {
|
||||||
|
val item = activeItems.find { it.id == itemID } ?: return
|
||||||
|
when(action){
|
||||||
|
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
||||||
|
cancelItem(itemID.toInt())
|
||||||
|
item.status = DownloadRepository.Status.Paused.toString()
|
||||||
|
downloadViewModel.updateDownload(item)
|
||||||
|
}
|
||||||
|
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
||||||
|
item.status = DownloadRepository.Status.Active.toString()
|
||||||
|
downloadViewModel.updateDownload(item)
|
||||||
|
runBlocking {
|
||||||
|
downloadViewModel.queueDownloads(listOf(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
override fun onCardClick() {
|
override fun onCardClick() {
|
||||||
this.dismiss()
|
this.dismiss()
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
|
|
@ -544,6 +558,12 @@ class ResultCardDetailsDialog(private val item: ResultItem) : BottomSheetDialogF
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun cancelItem(id: Int){
|
||||||
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
|
WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString())
|
||||||
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
|
}
|
||||||
|
|
||||||
private fun cancelActiveDownload(itemID: Long){
|
private fun cancelActiveDownload(itemID: Long){
|
||||||
val id = itemID.toInt()
|
val id = itemID.toInt()
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import android.view.View
|
||||||
import android.view.View.OnClickListener
|
import android.view.View.OnClickListener
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
|
@ -19,8 +20,11 @@ import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
|
||||||
import com.deniscerri.ytdlnis.util.NotificationUtil
|
import com.deniscerri.ytdlnis.util.NotificationUtil
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.yausername.youtubedl_android.YoutubeDL
|
import com.yausername.youtubedl_android.YoutubeDL
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
|
||||||
class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener {
|
class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickListener, OnClickListener {
|
||||||
|
|
@ -32,6 +36,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
lateinit var downloadItem: DownloadItem
|
lateinit var downloadItem: DownloadItem
|
||||||
private lateinit var notificationUtil: NotificationUtil
|
private lateinit var notificationUtil: NotificationUtil
|
||||||
private lateinit var list: List<DownloadItem>
|
private lateinit var list: List<DownloadItem>
|
||||||
|
private lateinit var pauseResume: MaterialButton
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
|
@ -39,7 +44,7 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
fragmentView = inflater.inflate(R.layout.fragment_generic_download_queue, container, false)
|
fragmentView = inflater.inflate(R.layout.fragment_active, container, false)
|
||||||
activity = getActivity()
|
activity = getActivity()
|
||||||
notificationUtil = NotificationUtil(requireContext())
|
notificationUtil = NotificationUtil(requireContext())
|
||||||
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
|
@ -59,10 +64,62 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
activeRecyclerView = view.findViewById(R.id.download_recyclerview)
|
activeRecyclerView = view.findViewById(R.id.download_recyclerview)
|
||||||
activeRecyclerView.adapter = activeDownloads
|
activeRecyclerView.adapter = activeDownloads
|
||||||
activeRecyclerView.layoutManager = GridLayoutManager(context, resources.getInteger(R.integer.grid_size))
|
activeRecyclerView.layoutManager = GridLayoutManager(context, resources.getInteger(R.integer.grid_size))
|
||||||
|
pauseResume = view.findViewById(R.id.pause_resume)
|
||||||
|
|
||||||
|
pauseResume.setOnClickListener {
|
||||||
|
if (pauseResume.text == requireContext().getString(R.string.pause)){
|
||||||
|
list.forEach {
|
||||||
|
cancelItem(it.id.toInt())
|
||||||
|
it.status = DownloadRepository.Status.Paused.toString()
|
||||||
|
downloadViewModel.updateDownload(it)
|
||||||
|
|
||||||
|
val card = view.findViewWithTag<MaterialCardView>("${it.id}##card")
|
||||||
|
val progressBar = card.findViewById<LinearProgressIndicator>(R.id.progress)
|
||||||
|
val pauseButton = card.findViewById<MaterialButton>(R.id.active_download_pause)
|
||||||
|
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_delete)
|
||||||
|
|
||||||
|
progressBar.isIndeterminate = false
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(requireContext(), R.drawable.exomedia_ic_play_arrow_white)
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Resume
|
||||||
|
cancelButton.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
val toQueue = list.filter { it.status == DownloadRepository.Status.Paused.toString() }
|
||||||
|
toQueue.forEach {
|
||||||
|
it.status = DownloadRepository.Status.Active.toString()
|
||||||
|
downloadViewModel.updateDownload(it)
|
||||||
|
|
||||||
|
val card = view.findViewWithTag<MaterialCardView>("${it.id}##card")
|
||||||
|
val progressBar = card.findViewById<LinearProgressIndicator>(R.id.progress)
|
||||||
|
val pauseButton = card.findViewById<MaterialButton>(R.id.active_download_pause)
|
||||||
|
val cancelButton = card.findViewById<MaterialButton>(R.id.active_download_delete)
|
||||||
|
|
||||||
|
pauseButton.icon = ContextCompat.getDrawable(requireContext(), R.drawable.exomedia_ic_pause_white)
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
cancelButton.visibility = View.GONE
|
||||||
|
pauseButton.tag = ActiveDownloadAdapter.ActiveDownloadAction.Pause
|
||||||
|
}
|
||||||
|
runBlocking {
|
||||||
|
downloadViewModel.queueDownloads(toQueue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
downloadViewModel.activeDownloads.observe(viewLifecycleOwner) {
|
downloadViewModel.activeDownloads.observe(viewLifecycleOwner) {
|
||||||
list = it
|
list = it
|
||||||
activeDownloads.submitList(it)
|
activeDownloads.submitList(it)
|
||||||
|
|
||||||
|
if (list.isNotEmpty()){
|
||||||
|
pauseResume.visibility = View.VISIBLE
|
||||||
|
if (list.all { l -> l.status == DownloadRepository.Status.Paused.toString() }){
|
||||||
|
pauseResume.text = requireContext().getString(R.string.resume)
|
||||||
|
}else{
|
||||||
|
pauseResume.text = requireContext().getString(R.string.pause)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pauseResume.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
it.forEach{item ->
|
it.forEach{item ->
|
||||||
WorkManager.getInstance(requireContext())
|
WorkManager.getInstance(requireContext())
|
||||||
.getWorkInfosForUniqueWorkLiveData(item.id.toString())
|
.getWorkInfosForUniqueWorkLiveData(item.id.toString())
|
||||||
|
|
@ -95,6 +152,25 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
cancelDownload(itemID)
|
cancelDownload(itemID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPauseClick(itemID: Long, action: ActiveDownloadAdapter.ActiveDownloadAction) {
|
||||||
|
val item = list.find { it.id == itemID } ?: return
|
||||||
|
when(action){
|
||||||
|
ActiveDownloadAdapter.ActiveDownloadAction.Pause -> {
|
||||||
|
cancelItem(itemID.toInt())
|
||||||
|
item.status = DownloadRepository.Status.Paused.toString()
|
||||||
|
downloadViewModel.updateDownload(item)
|
||||||
|
}
|
||||||
|
ActiveDownloadAdapter.ActiveDownloadAction.Resume -> {
|
||||||
|
item.status = DownloadRepository.Status.Active.toString()
|
||||||
|
downloadViewModel.updateDownload(item)
|
||||||
|
runBlocking {
|
||||||
|
downloadViewModel.queueDownloads(listOf(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOutputClick(item: DownloadItem) {
|
override fun onOutputClick(item: DownloadItem) {
|
||||||
if (item.logID != null) {
|
if (item.logID != null) {
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
|
|
@ -106,12 +182,14 @@ class ActiveDownloadsFragment : Fragment(), ActiveDownloadAdapter.OnItemClickLis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelDownload(itemID: Long){
|
private fun cancelItem(id: Int){
|
||||||
val id = itemID.toInt()
|
|
||||||
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
YoutubeDL.getInstance().destroyProcessById(id.toString())
|
||||||
WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString())
|
WorkManager.getInstance(requireContext()).cancelUniqueWork(id.toString())
|
||||||
notificationUtil.cancelDownloadNotification(id)
|
notificationUtil.cancelDownloadNotification(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelDownload(itemID: Long){
|
||||||
|
cancelItem(itemID.toInt())
|
||||||
list.find { it.id == itemID }?.let {
|
list.find { it.id == itemID }?.let {
|
||||||
it.status = DownloadRepository.Status.Cancelled.toString()
|
it.status = DownloadRepository.Status.Cancelled.toString()
|
||||||
downloadViewModel.updateDownload(it)
|
downloadViewModel.updateDownload(it)
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,6 @@ class DownloadQueueMainFragment : Fragment(){
|
||||||
when(m.itemId){
|
when(m.itemId){
|
||||||
R.id.clear_queue -> {
|
R.id.clear_queue -> {
|
||||||
showDeleteDialog {
|
showDeleteDialog {
|
||||||
cancelAllDownloads()
|
|
||||||
downloadViewModel.cancelQueued()
|
downloadViewModel.cancelQueued()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package com.deniscerri.ytdlnis.ui.more.settings
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.pm.ActivityInfo
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build.VERSION
|
import android.os.Build.VERSION
|
||||||
import android.os.Build.VERSION_CODES
|
import android.os.Build.VERSION_CODES
|
||||||
|
|
@ -18,10 +16,8 @@ import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.deniscerri.ytdlnis.MainActivity
|
import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.ui.more.TerminalActivity
|
|
||||||
import com.deniscerri.ytdlnis.util.ThemeUtil
|
import com.deniscerri.ytdlnis.util.ThemeUtil
|
||||||
import com.deniscerri.ytdlnis.util.UpdateUtil
|
import com.deniscerri.ytdlnis.util.UpdateUtil
|
||||||
import com.google.android.gms.common.wrappers.Wrappers.packageManager
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,7 +29,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
private var accent: ListPreference? = null
|
private var accent: ListPreference? = null
|
||||||
private var highContrast: SwitchPreferenceCompat? = null
|
private var highContrast: SwitchPreferenceCompat? = null
|
||||||
private var locale: ListPreference? = null
|
private var locale: ListPreference? = null
|
||||||
private var hideTerminal: SwitchPreferenceCompat? = null
|
private var showTerminalShareIcon: SwitchPreferenceCompat? = null
|
||||||
|
|
||||||
private var updateUtil: UpdateUtil? = null
|
private var updateUtil: UpdateUtil? = null
|
||||||
private var activeDownloadCount = 0
|
private var activeDownloadCount = 0
|
||||||
|
|
@ -54,7 +50,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
accent = findPreference("theme_accent")
|
accent = findPreference("theme_accent")
|
||||||
highContrast = findPreference("high_contrast")
|
highContrast = findPreference("high_contrast")
|
||||||
locale = findPreference("locale")
|
locale = findPreference("locale")
|
||||||
hideTerminal = findPreference("hide_terminal")
|
showTerminalShareIcon = findPreference("show_terminal")
|
||||||
|
|
||||||
if(VERSION.SDK_INT < VERSION_CODES.TIRAMISU){
|
if(VERSION.SDK_INT < VERSION_CODES.TIRAMISU){
|
||||||
val values = resources.getStringArray(R.array.language_values)
|
val values = resources.getStringArray(R.array.language_values)
|
||||||
|
|
@ -115,7 +111,7 @@ class GeneralSettingsFragment : BaseSettingsFragment() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
hideTerminal!!.onPreferenceChangeListener =
|
showTerminalShareIcon!!.onPreferenceChangeListener =
|
||||||
Preference.OnPreferenceChangeListener { pref: Preference?, _: Any ->
|
Preference.OnPreferenceChangeListener { pref: Preference?, _: Any ->
|
||||||
val packageManager = requireContext().packageManager
|
val packageManager = requireContext().packageManager
|
||||||
val aliasComponentName = ComponentName(requireContext(), "com.deniscerri.ytdlnis.terminalShareAlias")
|
val aliasComponentName = ComponentName(requireContext(), "com.deniscerri.ytdlnis.terminalShareAlias")
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,15 @@ package com.deniscerri.ytdlnis.util
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
|
import android.os.storage.StorageManager
|
||||||
|
import android.os.storage.StorageVolume
|
||||||
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
|
import androidx.core.net.toFile
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import com.anggrayudi.storage.callback.FileCallback
|
import com.anggrayudi.storage.callback.FileCallback
|
||||||
|
|
@ -12,11 +18,12 @@ import com.anggrayudi.storage.callback.FolderCallback
|
||||||
import com.anggrayudi.storage.file.copyFileTo
|
import com.anggrayudi.storage.file.copyFileTo
|
||||||
import com.anggrayudi.storage.file.copyFolderTo
|
import com.anggrayudi.storage.file.copyFolderTo
|
||||||
import com.anggrayudi.storage.file.getAbsolutePath
|
import com.anggrayudi.storage.file.getAbsolutePath
|
||||||
import com.anggrayudi.storage.file.moveFileTo
|
import com.anggrayudi.storage.file.getBasePath
|
||||||
import com.anggrayudi.storage.file.moveFolderTo
|
import com.deniscerri.ytdlnis.App
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.internal.closeQuietly
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
@ -32,15 +39,10 @@ import kotlin.math.pow
|
||||||
object FileUtil {
|
object FileUtil {
|
||||||
|
|
||||||
fun deleteFile(path: String){
|
fun deleteFile(path: String){
|
||||||
val file = File(path)
|
runCatching {
|
||||||
if (file.exists()) {
|
if (!File(path).delete()){
|
||||||
file.delete()
|
DocumentFile.fromSingleUri(App.instance, Uri.parse(path))?.delete()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal object Compare {
|
|
||||||
fun max(a: File, b: File): File {
|
|
||||||
return if (a.length() > b.length()) a else b
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +102,7 @@ object FileUtil {
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
curr.copyFolderTo(context, dst!!, skipEmptyFiles = false, callback = object : FolderCallback() {
|
curr.copyFolderTo(context, dst!!, skipEmptyFiles = false, callback = object : FolderCallback() {
|
||||||
override fun onStart(folder: DocumentFile, totalFilesToCopy: Int, workerThread: Thread): Long {
|
override fun onStart(folder: DocumentFile, totalFilesToCopy: Int, workerThread: Thread): Long {
|
||||||
return 1000 // update progress every 1 second
|
return 500 // update progress every half second
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onParentConflict(destinationFolder: DocumentFile, action: ParentFolderConflictAction, canMerge: Boolean) {
|
override fun onParentConflict(destinationFolder: DocumentFile, action: ParentFolderConflictAction, canMerge: Boolean) {
|
||||||
|
|
@ -120,11 +122,66 @@ object FileUtil {
|
||||||
it.deleteRecursively()
|
it.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFailed(errorCode: ErrorCode) {
|
||||||
|
//if its usb?
|
||||||
|
runCatching {
|
||||||
|
it.walkTopDown().forEach { f ->
|
||||||
|
if (f.isDirectory) return@forEach
|
||||||
|
|
||||||
|
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(f.extension) ?: "*/*"
|
||||||
|
|
||||||
|
val destUri = DocumentsContract.createDocument(
|
||||||
|
context.contentResolver,
|
||||||
|
dst.uri,
|
||||||
|
mimeType,
|
||||||
|
f.name
|
||||||
|
) ?: return@runCatching
|
||||||
|
|
||||||
|
val inputStream = f.inputStream()
|
||||||
|
val outputStream =
|
||||||
|
context.contentResolver.openOutputStream(destUri) ?: return@runCatching
|
||||||
|
inputStream.copyTo(outputStream)
|
||||||
|
inputStream.closeQuietly()
|
||||||
|
outputStream.closeQuietly()
|
||||||
|
|
||||||
|
fileList.add(DocumentFile.fromSingleUri(context, destUri)!!.getAbsolutePath(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
it.deleteRecursively()
|
||||||
|
}
|
||||||
|
super.onFailed(errorCode)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
withContext(Dispatchers.IO){
|
withContext(Dispatchers.IO){
|
||||||
curr.copyFileTo(context, dst!!, callback = object : FileCallback() {
|
curr.copyFileTo(context, dst!!, callback = object : FileCallback() {
|
||||||
|
override fun onFailed(errorCode: ErrorCode) {
|
||||||
|
//if its usb?
|
||||||
|
runCatching {
|
||||||
|
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(it.extension) ?: "*/*"
|
||||||
|
|
||||||
|
val destUri = DocumentsContract.createDocument(
|
||||||
|
context.contentResolver,
|
||||||
|
dst.uri,
|
||||||
|
mimeType,
|
||||||
|
it.name
|
||||||
|
) ?: return@runCatching
|
||||||
|
|
||||||
|
val inputStream = it.inputStream()
|
||||||
|
val outputStream =
|
||||||
|
context.contentResolver.openOutputStream(destUri) ?: return@runCatching
|
||||||
|
inputStream.copyTo(outputStream)
|
||||||
|
inputStream.closeQuietly()
|
||||||
|
outputStream.closeQuietly()
|
||||||
|
|
||||||
|
fileList.add(DocumentFile.fromSingleUri(context, destUri)!!.getAbsolutePath(context))
|
||||||
|
it.delete()
|
||||||
|
}
|
||||||
|
super.onFailed(errorCode)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStart(file: Any, workerThread: Thread): Long {
|
override fun onStart(file: Any, workerThread: Thread): Long {
|
||||||
return 1000 // update progress every 1 second
|
return 1000 // update progress every 1 second
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +193,7 @@ object FileUtil {
|
||||||
override fun onCompleted(result: Any) {
|
override fun onCompleted(result: Any) {
|
||||||
destFile = (result as DocumentFile)
|
destFile = (result as DocumentFile)
|
||||||
fileList.add(destFile.getAbsolutePath(context))
|
fileList.add(destFile.getAbsolutePath(context))
|
||||||
it.deleteRecursively()
|
it.delete()
|
||||||
super.onCompleted(result)
|
super.onCompleted(result)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -170,10 +227,9 @@ object FileUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun scanMedia(files: List<String>, context: Context) : List<String> {
|
private fun scanMedia(files: List<String>, context: Context) : List<String> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val paths = files.sortedByDescending { File(it).length() }
|
val paths = files.sortedByDescending { File(it).length() }
|
||||||
MediaScannerConnection.scanFile(context, paths.toTypedArray(), null, null)
|
runCatching {MediaScannerConnection.scanFile(context, paths.toTypedArray(), null, null) }
|
||||||
return paths
|
return paths
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import android.util.Log
|
||||||
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
|
||||||
|
import com.deniscerri.ytdlnis.database.Converters
|
||||||
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
import com.deniscerri.ytdlnis.database.models.ChapterItem
|
||||||
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
|
|
@ -452,12 +453,12 @@ class InfoUtil(private val context: Context) {
|
||||||
request.addOption("-R", "1")
|
request.addOption("-R", "1")
|
||||||
request.addOption("--socket-timeout", "5")
|
request.addOption("--socket-timeout", "5")
|
||||||
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
if (cookiesFile.exists()){
|
if (cookiesFile.exists()) {
|
||||||
request.addOption("--cookies", cookiesFile.absolutePath)
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
val proxy = sharedPreferences.getString("proxy", "")
|
val proxy = sharedPreferences.getString("proxy", "")
|
||||||
if (proxy!!.isNotBlank()){
|
if (proxy!!.isNotBlank()) {
|
||||||
request.addOption("--proxy", proxy)
|
request.addOption("--proxy", proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,34 +472,7 @@ class InfoUtil(private val context: Context) {
|
||||||
val json = results[0]
|
val json = results[0]
|
||||||
val jsonArray = JSONArray(json)
|
val jsonArray = JSONArray(json)
|
||||||
|
|
||||||
val formats : ArrayList<Format> = ArrayList()
|
return parseYTDLFormats(jsonArray)
|
||||||
for (f in 0 until jsonArray.length()){
|
|
||||||
val format = jsonArray.getJSONObject(f)
|
|
||||||
if (format.has("filesize")){
|
|
||||||
if (format.get("filesize") == "None"){
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", 0)
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
val size = format.get("filesize").toString().toFloat()
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", size)
|
|
||||||
}catch (ignored: Exception){}
|
|
||||||
}
|
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
|
||||||
if (format.has("format_note")){
|
|
||||||
if (!formatProper!!.format_note.contains("audio only", true)) {
|
|
||||||
formatProper.format_note = format.getString("format_note")
|
|
||||||
}else{
|
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (formatProper!!.format_note == "storyboard") continue
|
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
|
||||||
|
|
||||||
return formats
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Looper.prepare().run {
|
Looper.prepare().run {
|
||||||
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
|
||||||
|
|
@ -540,35 +514,8 @@ class InfoUtil(private val context: Context) {
|
||||||
|
|
||||||
YoutubeDL.getInstance().execute(request){ progress, _, line ->
|
YoutubeDL.getInstance().execute(request){ progress, _, line ->
|
||||||
try{
|
try{
|
||||||
val formats = mutableListOf<Format>()
|
|
||||||
val listOfStrings = JSONArray(line)
|
val listOfStrings = JSONArray(line)
|
||||||
for (f in 0 until listOfStrings.length()){
|
progress(parseYTDLFormats(listOfStrings))
|
||||||
val format = listOfStrings.get(f) as JSONObject
|
|
||||||
try{
|
|
||||||
if (format.getString("filesize") == "None") continue
|
|
||||||
}catch (e: Exception) { continue }
|
|
||||||
if (format.has("filesize")){
|
|
||||||
if (format.get("filesize") == "None"){
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", 0)
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
val size = format.get("filesize").toString().toFloat()
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", size)
|
|
||||||
}catch (ignored: Exception){}
|
|
||||||
}
|
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
|
||||||
if ( !formatProper!!.format_note.contains("audio only", true)) {
|
|
||||||
formatProper.format_note = format.getString("format_note")
|
|
||||||
}else{
|
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
|
||||||
}
|
|
||||||
if (formatProper.format_note == "storyboard") continue
|
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
|
||||||
progress(formats)
|
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
progress(emptyList())
|
progress(emptyList())
|
||||||
}
|
}
|
||||||
|
|
@ -668,37 +615,7 @@ class InfoUtil(private val context: Context) {
|
||||||
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
if (jsonObject.has("playlist_title")) playlistTitle = jsonObject.getString("playlist_title")
|
||||||
if(playlistTitle.equals(query)) playlistTitle = ""
|
if(playlistTitle.equals(query)) playlistTitle = ""
|
||||||
val formatsInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JSONArray) jsonObject.getJSONArray("formats") else null
|
val formatsInJSON = if (jsonObject.has("formats") && jsonObject.get("formats") is JSONArray) jsonObject.getJSONArray("formats") else null
|
||||||
val formats : ArrayList<Format> = ArrayList()
|
val formats : ArrayList<Format> = parseYTDLFormats(formatsInJSON)
|
||||||
if (formatsInJSON != null) {
|
|
||||||
for (f in 0 until formatsInJSON.length()){
|
|
||||||
val format = formatsInJSON.getJSONObject(f)
|
|
||||||
if (format.has("filesize")){
|
|
||||||
if (format.get("filesize") == "None"){
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", 0)
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
val size = format.get("filesize").toString().toFloat()
|
|
||||||
format.remove("filesize")
|
|
||||||
format.put("filesize", size)
|
|
||||||
}catch (ignored: Exception){}
|
|
||||||
}
|
|
||||||
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
|
||||||
if (formatProper.format_note == null) continue
|
|
||||||
if (format.has("format_note")){
|
|
||||||
if (!formatProper!!.format_note.contains("audio only", true)) {
|
|
||||||
formatProper.format_note = format.getString("format_note")
|
|
||||||
}else{
|
|
||||||
if (!formatProper.format_note.endsWith("audio", true)){
|
|
||||||
formatProper.format_note = "${format.getString("format_note")} audio"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (formatProper.format_note == "storyboard") continue
|
|
||||||
formatProper.container = format.getString("ext")
|
|
||||||
formats.add(formatProper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val chaptersInJSON = if (jsonObject.has("chapters") && jsonObject.get("chapters") is JSONArray) jsonObject.getJSONArray("chapters") else null
|
val chaptersInJSON = if (jsonObject.has("chapters") && jsonObject.get("chapters") is JSONArray) jsonObject.getJSONArray("chapters") else null
|
||||||
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
val listType: Type = object : TypeToken<List<ChapterItem>>() {}.type
|
||||||
|
|
@ -734,6 +651,47 @@ class InfoUtil(private val context: Context) {
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun parseYTDLFormats(formatsInJSON: JSONArray?) : ArrayList<Format> {
|
||||||
|
val formats = arrayListOf<Format>()
|
||||||
|
|
||||||
|
if (formatsInJSON != null) {
|
||||||
|
for (f in 0 until formatsInJSON.length()){
|
||||||
|
val format = formatsInJSON.getJSONObject(f)
|
||||||
|
if (format.has("filesize")){
|
||||||
|
if (format.get("filesize") == "None"){
|
||||||
|
format.remove("filesize")
|
||||||
|
if (format.has("filesize_approx") && format.get("filesize_approx") != "None"){
|
||||||
|
format.put("filesize", format.getInt("filesize_approx"))
|
||||||
|
}else{
|
||||||
|
format.put("filesize", 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
val size = format.get("filesize").toString().toFloat()
|
||||||
|
format.remove("filesize")
|
||||||
|
format.put("filesize", size)
|
||||||
|
}catch (ignored: Exception){}
|
||||||
|
}
|
||||||
|
val formatProper = Gson().fromJson(format.toString(), Format::class.java)
|
||||||
|
if (formatProper.format_note == null) continue
|
||||||
|
if (format.has("format_note")){
|
||||||
|
if (!formatProper!!.format_note.contains("audio only", true)) {
|
||||||
|
formatProper.format_note = format.getString("format_note")
|
||||||
|
}else{
|
||||||
|
if (!formatProper.format_note.endsWith("audio", true)){
|
||||||
|
formatProper.format_note = "${format.getString("format_note")} audio"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (formatProper.format_note == "storyboard") continue
|
||||||
|
formatProper.container = format.getString("ext")
|
||||||
|
formats.add(formatProper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats
|
||||||
|
}
|
||||||
|
|
||||||
fun getMissingInfo(url: String): ResultItem? {
|
fun getMissingInfo(url: String): ResultItem? {
|
||||||
try {
|
try {
|
||||||
val request = YoutubeDLRequest(url)
|
val request = YoutubeDLRequest(url)
|
||||||
|
|
@ -885,33 +843,57 @@ class InfoUtil(private val context: Context) {
|
||||||
|
|
||||||
fun getStreamingUrlAndChapters(url: String) : MutableList<String?> {
|
fun getStreamingUrlAndChapters(url: String) : MutableList<String?> {
|
||||||
try {
|
try {
|
||||||
val request = YoutubeDLRequest(url)
|
val p = Pattern.compile("(^(https?)://(www.)?(music.)?youtu(.be)?)|(^(https?)://(www.)?piped.video)")
|
||||||
request.addOption("--get-url")
|
val m = p.matcher(url)
|
||||||
request.addOption("--print", "%(chapters)s")
|
|
||||||
request.addOption("--skip-download")
|
|
||||||
request.addOption("-R", "1")
|
|
||||||
request.addOption("--socket-timeout", "5")
|
|
||||||
|
|
||||||
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
if (m.find()){
|
||||||
if (cookiesFile.exists()){
|
return getStreamingUrlAndChaptersFromPIPED(getIDFromYoutubeURL(url))
|
||||||
request.addOption("--cookies", cookiesFile.absolutePath)
|
}else{
|
||||||
|
throw Exception()
|
||||||
}
|
}
|
||||||
|
}catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
val request = YoutubeDLRequest(url)
|
||||||
|
request.addOption("--get-url")
|
||||||
|
request.addOption("--print", "%(chapters)s")
|
||||||
|
request.addOption("--skip-download")
|
||||||
|
request.addOption("-R", "1")
|
||||||
|
request.addOption("--socket-timeout", "5")
|
||||||
|
|
||||||
val proxy = sharedPreferences.getString("proxy", "")
|
val cookiesFile = File(context.cacheDir, "cookies.txt")
|
||||||
if (proxy!!.isNotBlank()){
|
if (cookiesFile.exists()){
|
||||||
request.addOption("--proxy", proxy)
|
request.addOption("--cookies", cookiesFile.absolutePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
val proxy = sharedPreferences.getString("proxy", "")
|
||||||
val results: Array<String?> = try {
|
if (proxy!!.isNotBlank()){
|
||||||
val lineSeparator = System.getProperty("line.separator")
|
request.addOption("--proxy", proxy)
|
||||||
youtubeDLResponse.out.split(lineSeparator!!).toTypedArray()
|
}
|
||||||
|
|
||||||
|
val youtubeDLResponse = YoutubeDL.getInstance().execute(request)
|
||||||
|
val results: Array<String?> = try {
|
||||||
|
val lineSeparator = System.getProperty("line.separator")
|
||||||
|
youtubeDLResponse.out.split(lineSeparator!!).toTypedArray()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
arrayOf(youtubeDLResponse.out)
|
||||||
|
}
|
||||||
|
return results.filter { it!!.isNotEmpty() }.toMutableList()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
arrayOf(youtubeDLResponse.out)
|
return mutableListOf()
|
||||||
}
|
}
|
||||||
return results.filter { it!!.isNotEmpty() }.toMutableList()
|
}
|
||||||
} catch (e: Exception) {
|
}
|
||||||
return mutableListOf()
|
|
||||||
|
private fun getStreamingUrlAndChaptersFromPIPED(id: String) : MutableList<String?> {
|
||||||
|
val res = genericRequest("$pipedURL/streams/$id")
|
||||||
|
if (res.length() == 0) {
|
||||||
|
throw Exception()
|
||||||
|
}else{
|
||||||
|
val item = createVideoFromPipedJSON(res, id)
|
||||||
|
if (item!!.urls.isBlank()) throw Exception()
|
||||||
|
val list = mutableListOf<String?>(Gson().toJson(item.chapters))
|
||||||
|
list.addAll(item.urls.split(","))
|
||||||
|
return list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -978,7 +960,6 @@ class InfoUtil(private val context: Context) {
|
||||||
request.addCommands(listOf("--replace-in-metadata","uploader",".*.",downloadItem.author.take(25)))
|
request.addCommands(listOf("--replace-in-metadata","uploader",".*.",downloadItem.author.take(25)))
|
||||||
}
|
}
|
||||||
request.addCommands(listOf("--replace-in-metadata","uploader"," - Topic$",""))
|
request.addCommands(listOf("--replace-in-metadata","uploader"," - Topic$",""))
|
||||||
if (downloadItem.customFileNameTemplate.isBlank()) downloadItem.customFileNameTemplate = "%(uploader|${downloadItem.author})s - %(title)s"
|
|
||||||
downloadItem.customFileNameTemplate = downloadItem.customFileNameTemplate.replace("%(uploader)s", "%(uploader|${downloadItem.author})s")
|
downloadItem.customFileNameTemplate = downloadItem.customFileNameTemplate.replace("%(uploader)s", "%(uploader|${downloadItem.author})s")
|
||||||
|
|
||||||
if (downloadItem.downloadSections.isNotBlank()){
|
if (downloadItem.downloadSections.isNotBlank()){
|
||||||
|
|
@ -1050,38 +1031,41 @@ class InfoUtil(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.addOption("--embed-metadata")
|
|
||||||
|
|
||||||
if (downloadItem.audioPreferences.embedThumb) {
|
|
||||||
request.addOption("--embed-thumbnail")
|
|
||||||
request.addOption("--convert-thumbnails", "jpg")
|
|
||||||
if (sharedPreferences.getBoolean("crop_thumbnail", true)){
|
|
||||||
try {
|
|
||||||
val config = File(context.cacheDir.absolutePath + "/downloads/${downloadItem.id}/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
|
|
||||||
val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
|
||||||
config.writeText(configData)
|
|
||||||
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
|
||||||
request.addOption("--config", config.absolutePath)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.addOption("--parse-metadata", "%(release_year,upload_date)s:%(meta_date)s")
|
|
||||||
|
|
||||||
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("-P", tempFileDir.absolutePath)
|
request.addOption("-P", tempFileDir.absolutePath)
|
||||||
|
|
||||||
if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
||||||
request.addOption("--split-chapters")
|
request.addOption("--split-chapters")
|
||||||
|
request.addOption("-o", "chapter:%(section_title)s.%(ext)s")
|
||||||
}else{
|
}else{
|
||||||
request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s")
|
request.addOption("--embed-metadata")
|
||||||
|
|
||||||
|
if (downloadItem.audioPreferences.embedThumb) {
|
||||||
|
request.addOption("--embed-thumbnail")
|
||||||
|
request.addOption("--convert-thumbnails", "jpg")
|
||||||
|
if (sharedPreferences.getBoolean("crop_thumbnail", true)){
|
||||||
|
try {
|
||||||
|
val config = File(context.cacheDir.absolutePath + "/downloads/${downloadItem.id}/config" + downloadItem.title + "##" + downloadItem.format.format_id + ".txt")
|
||||||
|
val configData = "--ppa \"ffmpeg: -c:v mjpeg -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||||
|
config.writeText(configData)
|
||||||
|
request.addOption("--ppa", "ThumbnailsConvertor:-qmin 1 -q:v 1")
|
||||||
|
request.addOption("--config", config.absolutePath)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.addOption("--parse-metadata", "%(release_year,upload_date)s:%(meta_date)s")
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloadItem.customFileNameTemplate.isNotBlank()){
|
||||||
|
request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1149,7 +1133,9 @@ class InfoUtil(private val context: Context) {
|
||||||
if (downloadItem.videoPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
if (downloadItem.videoPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
|
||||||
request.addOption("--split-chapters")
|
request.addOption("--split-chapters")
|
||||||
}else{
|
}else{
|
||||||
request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s")
|
if (downloadItem.customFileNameTemplate.isNotBlank()){
|
||||||
|
request.addOption("-o", "${downloadItem.customFileNameTemplate}.%(ext)s")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ object ThemeUtil {
|
||||||
private fun getThemeColor(context: Context, colorCode: Int): Int {
|
private fun getThemeColor(context: Context, colorCode: Int): Int {
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
val accent = sharedPreferences.getString("theme_accent", "blue")
|
val accent = sharedPreferences.getString("theme_accent", "blue")
|
||||||
return if (accent == "Default" || accent == "blue"){
|
return if (accent == "blue"){
|
||||||
"c22727".toInt(16)
|
"d43c3b".toInt(16)
|
||||||
}else{
|
}else{
|
||||||
val value = TypedValue()
|
val value = TypedValue()
|
||||||
context.theme.resolveAttribute(colorCode, value, true)
|
context.theme.resolveAttribute(colorCode, value, true)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
@ -251,7 +252,7 @@ object UiUtil {
|
||||||
fragmentContext.packageName + ".fileprovider",
|
fragmentContext.packageName + ".fileprovider",
|
||||||
file
|
file
|
||||||
)
|
)
|
||||||
val mime = fragmentContext.contentResolver.getType(uri)
|
val mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension)
|
||||||
val i = Intent(Intent.ACTION_VIEW)
|
val i = Intent(Intent.ACTION_VIEW)
|
||||||
i.setDataAndType(uri, mime)
|
i.setDataAndType(uri, mime)
|
||||||
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class DownloadWorker(
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadItem.status != DownloadRepository.Status.Queued.toString()) return Result.failure()
|
if (downloadItem.status != DownloadRepository.Status.Queued.toString() && downloadItem.status != DownloadRepository.Status.Paused.toString()) return Result.failure()
|
||||||
|
|
||||||
val pendingIntent = NavDeepLinkBuilder(context)
|
val pendingIntent = NavDeepLinkBuilder(context)
|
||||||
.setGraph(R.navigation.nav_graph)
|
.setGraph(R.navigation.nav_graph)
|
||||||
|
|
@ -134,7 +134,7 @@ class DownloadWorker(
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
val wasQuickDownloaded = updateDownloadItem(downloadItem, infoUtil, dao, resultDao)
|
val wasQuickDownloaded = updateDownloadItem(downloadItem, infoUtil, dao, resultDao)
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
runBlocking {
|
||||||
var finalPaths : List<String>?
|
var finalPaths : List<String>?
|
||||||
//move file from internal to set download directory
|
//move file from internal to set download directory
|
||||||
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
setProgressAsync(workDataOf("progress" to 100, "output" to "Moving file to ${FileUtil.formatPath(downloadLocation)}", "id" to downloadItem.id, "log" to logDownloads))
|
||||||
|
|
@ -174,30 +174,26 @@ class DownloadWorker(
|
||||||
downloadItem.title, if (finalPaths?.first().equals(context.getString(R.string.unfound_file))) null else finalPaths,
|
downloadItem.title, if (finalPaths?.first().equals(context.getString(R.string.unfound_file))) null else finalPaths,
|
||||||
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
|
NotificationUtil.DOWNLOAD_FINISHED_CHANNEL_ID
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (wasQuickDownloaded){
|
if (wasQuickDownloaded){
|
||||||
runCatching {
|
runCatching {
|
||||||
setProgressAsync(workDataOf("progress" to 100, "output" to "Creating Result Items", "id" to downloadItem.id, "log" to false))
|
setProgressAsync(workDataOf("progress" to 100, "output" to "Creating Result Items", "id" to downloadItem.id, "log" to false))
|
||||||
runBlocking {
|
runBlocking {
|
||||||
infoUtil.getFromYTDL(downloadItem.url).forEach { res ->
|
infoUtil.getFromYTDL(downloadItem.url).forEach { res ->
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
resultDao.insert(res)
|
resultDao.insert(res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
dao.delete(downloadItem.id)
|
dao.delete(downloadItem.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
if (it is YoutubeDL.CanceledException) {
|
if (it is YoutubeDL.CanceledException) {
|
||||||
downloadItem.status = DownloadRepository.Status.Cancelled.toString()
|
|
||||||
runBlocking {
|
|
||||||
dao.update(downloadItem)
|
|
||||||
}
|
|
||||||
return Result.failure(
|
return Result.failure(
|
||||||
Data.Builder().putString("output", "Download has been cancelled!").build()
|
Data.Builder().putString("output", "Download has been cancelled!").build()
|
||||||
)
|
)
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/ic_refresh_white.xml
Normal file
5
app/src/main/res/drawable/ic_refresh_white.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<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:textColorPrimary" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
|
||||||
|
</vector>
|
||||||
12
app/src/main/res/drawable/line.xml
Normal file
12
app/src/main/res/drawable/line.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
|
||||||
|
<solid android:color="@android:color/transparent" />
|
||||||
|
|
||||||
|
<padding
|
||||||
|
android:top="10dp"
|
||||||
|
android:left="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:bottom="10dp"/>
|
||||||
|
</shape>
|
||||||
9
app/src/main/res/drawable/line_drawable.xml
Normal file
9
app/src/main/res/drawable/line_drawable.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:state_pressed="true"
|
||||||
|
android:drawable="@drawable/line"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/line"/>
|
||||||
|
</selector>
|
||||||
18
app/src/main/res/drawable/thumb.xml
Normal file
18
app/src/main/res/drawable/thumb.xml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:pivotX="65%"
|
||||||
|
android:pivotY="20%"
|
||||||
|
android:toDegrees="250"
|
||||||
|
android:fromDegrees="270">
|
||||||
|
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="?android:colorAccent"/>
|
||||||
|
<size
|
||||||
|
android:width="40dp"
|
||||||
|
android:height="20dp"/>
|
||||||
|
<corners
|
||||||
|
android:topLeftRadius="20dp"
|
||||||
|
android:topRightRadius="20dp"/>
|
||||||
|
</shape>
|
||||||
|
|
||||||
|
</rotate>
|
||||||
8
app/src/main/res/drawable/thumb_drawable.xml
Normal file
8
app/src/main/res/drawable/thumb_drawable.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:state_pressed="true"
|
||||||
|
android:drawable="@drawable/thumb"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:drawable="@drawable/thumb"/>
|
||||||
|
</selector>
|
||||||
|
|
@ -27,6 +27,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/providers"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
app:singleSelection="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
style="@style/Divider.Vertical"/>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/queries_constraint"
|
android:id="@+id/queries_constraint"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -132,9 +154,12 @@
|
||||||
android:id="@+id/recyclerViewHome"
|
android:id="@+id/recyclerViewHome"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="none"
|
||||||
android:layout_marginLeft="10dp"
|
app:fastScrollEnabled="true"
|
||||||
android:layout_marginRight="10dp"
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="100dp"
|
android:paddingBottom="100dp"
|
||||||
app:spanCount="3"
|
app:spanCount="3"
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/providers"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
app:singleSelection="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
style="@style/Divider.Vertical"/>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/queries_constraint"
|
android:id="@+id/queries_constraint"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -147,9 +169,13 @@
|
||||||
android:id="@+id/recyclerViewHome"
|
android:id="@+id/recyclerViewHome"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="none"
|
||||||
android:layout_marginLeft="10dp"
|
app:fastScrollEnabled="true"
|
||||||
android:layout_marginRight="10dp"
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="100dp"
|
android:paddingBottom="100dp"
|
||||||
app:spanCount="2"
|
app:spanCount="2"
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/providers"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:singleSelection="true"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
style="@style/Divider.Vertical"/>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/queries_constraint"
|
android:id="@+id/queries_constraint"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -132,9 +154,12 @@
|
||||||
android:id="@+id/recyclerViewHome"
|
android:id="@+id/recyclerViewHome"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="none"
|
||||||
android:layout_marginLeft="10dp"
|
app:fastScrollEnabled="true"
|
||||||
android:layout_marginRight="10dp"
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="100dp"
|
android:paddingBottom="100dp"
|
||||||
app:spanCount="4"
|
app:spanCount="4"
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
android:dividerPadding="5dp"
|
android:dividerPadding="5dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/active_download_cancel"
|
app:layout_constraintEnd_toStartOf="@+id/active_download_pause"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview">
|
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview">
|
||||||
|
|
@ -152,14 +152,30 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/active_download_cancel"
|
android:id="@+id/active_download_pause"
|
||||||
style="?attr/materialIconButtonFilledStyle"
|
style="?attr/materialIconButtonFilledStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:backgroundTint="?attr/colorSurface"
|
app:backgroundTint="?attr/colorSurface"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:icon="@drawable/ic_cancel"
|
android:layout_marginEnd="5dp"
|
||||||
|
app:icon="@drawable/exomedia_ic_play_arrow_white"
|
||||||
|
app:iconSize="30dp"
|
||||||
|
app:iconTint="?android:textColorPrimary"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/active_download_delete"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/linearlayout2_horizontalscrollview"
|
||||||
|
app:layout_constraintVertical_bias="0.51" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/active_download_delete"
|
||||||
|
style="?attr/materialIconButtonFilledStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
app:backgroundTint="?attr/colorSurface"
|
||||||
|
app:cornerRadius="15dp"
|
||||||
|
app:icon="@drawable/baseline_delete_24"
|
||||||
app:iconSize="30dp"
|
app:iconSize="30dp"
|
||||||
app:iconTint="?android:textColorPrimary"
|
app:iconTint="?android:textColorPrimary"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/output"
|
app:layout_constraintBottom_toTopOf="@+id/output"
|
||||||
|
|
|
||||||
|
|
@ -15,63 +15,53 @@
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||||
app:strokeWidth="0dp"
|
app:strokeWidth="0dp"
|
||||||
app:cardElevation="10dp"
|
|
||||||
app:cardMaxElevation="12dp"
|
|
||||||
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">
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
|
||||||
android:id="@+id/progress"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:alpha="0.3"
|
|
||||||
android:scaleY="200"
|
|
||||||
app:trackColor="#000" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:paddingHorizontal="20dp"
|
android:paddingHorizontal="10dp"
|
||||||
android:paddingVertical="10dp"
|
android:paddingVertical="10dp"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<FrameLayout
|
||||||
android:id="@+id/image_view"
|
android:id="@+id/image_frame"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintVertical_bias="0.0"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="?attr/colorSurfaceVariant"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintDimensionRatio="H,16:9"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/download_item_data"
|
|
||||||
app:layout_constraintHorizontal_weight="0.3"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar" />
|
app:layout_constraintDimensionRatio="H,16:9"
|
||||||
|
app:shapeAppearance="@style/ShapeAppearanceOverlay.Avatar"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/download_item_data"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
>
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
android:id="@+id/progress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:elevation="10dp"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/image_view"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/image_view"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/image_view"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/image_view"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:scaleY="200"
|
||||||
|
app:trackColor="#000" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/duration"
|
android:id="@+id/image_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_margin="5dp"
|
app:layout_constraintVertical_bias="0.0"
|
||||||
android:background="#80000000"
|
android:background="?attr/colorSurfaceVariant"
|
||||||
android:clickable="false"
|
android:scaleType="centerCrop"/>
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center"
|
</FrameLayout>
|
||||||
android:maxLength="17"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minWidth="30dp"
|
|
||||||
android:paddingHorizontal="5dp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:cornerRadius="10dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/image_view"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/image_view" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/download_item_data"
|
android:id="@+id/download_item_data"
|
||||||
|
|
@ -79,9 +69,9 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@id/active_download_cancel"
|
app:layout_constraintEnd_toStartOf="@id/active_download_pause"
|
||||||
app:layout_constraintHorizontal_weight="0.7"
|
app:layout_constraintHorizontal_weight="0.7"
|
||||||
app:layout_constraintStart_toEndOf="@+id/image_view"
|
app:layout_constraintStart_toEndOf="@+id/image_frame"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
@ -139,14 +129,29 @@
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/active_download_cancel"
|
android:id="@+id/active_download_pause"
|
||||||
style="?attr/materialIconButtonFilledStyle"
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
app:layout_constraintVertical_bias="0.0"
|
app:layout_constraintVertical_bias="0.0"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:backgroundTint="?attr/colorSurface"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
app:cornerRadius="15dp"
|
app:cornerRadius="15dp"
|
||||||
app:icon="@drawable/ic_cancel"
|
app:icon="@drawable/exomedia_ic_pause_white"
|
||||||
|
app:iconSize="30dp"
|
||||||
|
app:iconTint="?android:textColorPrimary"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/active_download_delete"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/active_download_delete"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton"
|
||||||
|
app:layout_constraintVertical_bias="0.0"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
app:cornerRadius="15dp"
|
||||||
|
app:icon="@drawable/baseline_delete_24"
|
||||||
app:iconSize="30dp"
|
app:iconSize="30dp"
|
||||||
app:iconTint="?android:textColorPrimary"
|
app:iconTint="?android:textColorPrimary"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
@ -159,7 +164,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:barrierDirection="bottom"
|
app:barrierDirection="bottom"
|
||||||
app:constraint_referenced_ids="download_item_data,active_download_cancel" />
|
app:constraint_referenced_ids="download_item_data,active_download_delete" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/from_textinput"
|
android:id="@+id/from_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="80dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/start">
|
android:hint="@string/start">
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/to_textinput"
|
android:id="@+id/to_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="80dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/end"
|
android:hint="@string/end"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,11 @@
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
android:paddingBottom="70dp"
|
android:paddingBottom="70dp"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
|
|
||||||
41
app/src/main/res/layout/fragment_active.xml
Normal file
41
app/src/main/res/layout/fragment_active.xml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="100dp"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/pause_resume"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="30dp"
|
||||||
|
android:paddingVertical="10dp"
|
||||||
|
android:text="@string/resume"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/download_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/pause_resume">
|
||||||
|
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -4,6 +4,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="200dp"
|
android:layout_marginBottom="200dp"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,11 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
android:layout_marginLeft="10dp"
|
app:fastScrollEnabled="true"
|
||||||
android:layout_marginRight="10dp"
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="100dp"
|
android:paddingBottom="100dp"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,28 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/providers"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:chipSpacingVertical="-10dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
app:singleSelection="true"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
style="@style/Divider.Vertical"/>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/queries_constraint"
|
android:id="@+id/queries_constraint"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -135,11 +157,16 @@
|
||||||
android:id="@+id/recyclerViewHome"
|
android:id="@+id/recyclerViewHome"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="none"
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginRight="10dp"
|
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingBottom="100dp"
|
android:paddingBottom="100dp"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="100dp"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
@ -22,6 +23,11 @@
|
||||||
android:id="@+id/download_recyclerview"
|
android:id="@+id/download_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,7 +55,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:dividerPadding="5dp"
|
android:dividerPadding="5dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/download_button_layout"
|
app:layout_constraintBottom_toTopOf="@+id/download_music"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
@ -62,15 +64,15 @@
|
||||||
android:id="@+id/result_title"
|
android:id="@+id/result_title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:paddingStart="10dp"
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
android:paddingEnd="10dp"
|
android:paddingEnd="10dp"
|
||||||
|
android:scrollbars="none"
|
||||||
android:shadowColor="@color/black"
|
android:shadowColor="@color/black"
|
||||||
android:shadowDx="4"
|
android:shadowDx="4"
|
||||||
android:shadowDy="4"
|
android:shadowDy="4"
|
||||||
android:scrollbars="none"
|
|
||||||
android:shadowRadius="2"
|
android:shadowRadius="2"
|
||||||
android:textColor="#FFF"
|
android:textColor="#FFF"
|
||||||
android:textSize="17sp"
|
android:textSize="17sp"
|
||||||
|
|
@ -80,15 +82,15 @@
|
||||||
android:id="@+id/author"
|
android:id="@+id/author"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="bottom"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:gravity="bottom"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="10dp"
|
||||||
android:paddingEnd="10dp"
|
android:paddingEnd="10dp"
|
||||||
|
android:scrollbars="none"
|
||||||
android:shadowColor="@color/black"
|
android:shadowColor="@color/black"
|
||||||
android:shadowDx="4"
|
android:shadowDx="4"
|
||||||
android:shadowDy="4"
|
android:shadowDy="4"
|
||||||
android:scrollbars="none"
|
|
||||||
android:shadowRadius="1.5"
|
android:shadowRadius="1.5"
|
||||||
android:textColor="#FFF"
|
android:textColor="#FFF"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
|
|
@ -115,33 +117,32 @@
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/download_button_layout"
|
android:id="@+id/download_music"
|
||||||
android:layout_width="wrap_content"
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="55dp"
|
||||||
android:orientation="horizontal"
|
app:elevation="0dp"
|
||||||
android:padding="5dp"
|
android:elevation="0dp"
|
||||||
|
app:borderWidth="0dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_marginVertical="10dp"
|
||||||
|
android:layout_marginHorizontal="5dp"
|
||||||
|
app:icon="@drawable/ic_music"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
app:layout_constraintEnd_toStartOf="@+id/download_video" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/download_music"
|
android:id="@+id/download_video"
|
||||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
android:layout_width="55dp"
|
android:layout_width="55dp"
|
||||||
android:layout_height="55dp"
|
android:layout_height="55dp"
|
||||||
android:layout_marginVertical="5dp"
|
android:layout_margin="10dp"
|
||||||
android:layout_marginStart="5dp"
|
app:elevation="0dp"
|
||||||
app:icon="@drawable/ic_music" />
|
android:elevation="0dp"
|
||||||
|
app:borderWidth="0dp"
|
||||||
<com.google.android.material.button.MaterialButton
|
app:icon="@drawable/ic_video"
|
||||||
android:id="@+id/download_video"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
android:layout_width="55dp"
|
|
||||||
android:layout_height="55dp"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
app:icon="@drawable/ic_video" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="20dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
|
@ -85,7 +86,7 @@
|
||||||
android:singleLine="false"
|
android:singleLine="false"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textSize="17sp"
|
android:textSize="17sp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/download_button_layout"
|
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
@ -94,53 +95,46 @@
|
||||||
android:id="@+id/bottom_info"
|
android:id="@+id/bottom_info"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:singleLine="false"
|
android:singleLine="false"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/download_button_layout"
|
app:layout_constraintEnd_toStartOf="@+id/download_music"
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/title" />
|
app:layout_constraintTop_toBottomOf="@id/title" />
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/download_button_layout"
|
android:id="@+id/download_music"
|
||||||
android:layout_width="wrap_content"
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="55dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_height="55dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginVertical="10dp"
|
||||||
android:orientation="horizontal"
|
android:layout_marginEnd="5dp"
|
||||||
|
app:icon="@drawable/ic_music"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/download_video"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/download_video"
|
||||||
|
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
||||||
|
android:layout_width="55dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:icon="@drawable/ic_video"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/download_music"
|
|
||||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
|
||||||
android:layout_width="55dp"
|
|
||||||
android:layout_height="55dp"
|
|
||||||
android:layout_marginVertical="5dp"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
app:icon="@drawable/ic_music" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/download_video"
|
|
||||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
|
|
||||||
android:layout_width="55dp"
|
|
||||||
android:layout_height="55dp"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
app:icon="@drawable/ic_video" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/title_barrier"
|
android:id="@+id/title_barrier"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:barrierDirection="bottom"
|
app:barrierDirection="bottom"
|
||||||
app:constraint_referenced_ids="bottom_info,download_button_layout" />
|
app:constraint_referenced_ids="bottom_info,download_music" />
|
||||||
|
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
@ -96,10 +95,9 @@
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/from_textinput"
|
android:id="@+id/from_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
android:layout_width="70dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/start">
|
android:hint="@string/start">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
|
@ -112,10 +110,9 @@
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/to_textinput"
|
android:id="@+id/to_textinput"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox"
|
||||||
android:layout_width="70dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:hint="@string/end"
|
android:hint="@string/end"
|
||||||
app:errorEnabled="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/colon">
|
app:layout_constraintStart_toEndOf="@+id/colon">
|
||||||
|
|
||||||
|
|
@ -139,6 +136,11 @@
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="80dp"
|
android:paddingBottom="80dp"
|
||||||
|
app:fastScrollEnabled="true"
|
||||||
|
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
|
||||||
|
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
||||||
|
app:fastScrollVerticalTrackDrawable="@drawable/line_drawable"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/redownload"
|
android:id="@+id/redownload"
|
||||||
android:title="@string/redownload"
|
android:title="@string/redownload"
|
||||||
android:icon="@drawable/ic_refresh"
|
android:icon="@drawable/ic_refresh_white"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
|
|
|
||||||
|
|
@ -241,8 +241,7 @@
|
||||||
<string name="sponsorblock">حاجب شرائح الإعلانات</string>
|
<string name="sponsorblock">حاجب شرائح الإعلانات</string>
|
||||||
<string name="keep_cache">الاحتفاظ بالملفات المؤقتة</string>
|
<string name="keep_cache">الاحتفاظ بالملفات المؤقتة</string>
|
||||||
<string name="backup">عمل نسخة احتياطية</string>
|
<string name="backup">عمل نسخة احتياطية</string>
|
||||||
<string name="pause">إيقاف
|
<string name="pause">إيقاف</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">استئناف</string>
|
<string name="resume">استئناف</string>
|
||||||
<string name="updating_download_data">يتم جلب بيانات التحميل</string>
|
<string name="updating_download_data">يتم جلب بيانات التحميل</string>
|
||||||
<string name="keep_cache_summary">عدم مسح ملفات الكاش بعد اكتمال التحميل</string>
|
<string name="keep_cache_summary">عدم مسح ملفات الكاش بعد اكتمال التحميل</string>
|
||||||
|
|
|
||||||
|
|
@ -236,8 +236,7 @@
|
||||||
<string name="preferred_format_id">Üstünlük Verilən Format ID</string>
|
<string name="preferred_format_id">Üstünlük Verilən Format ID</string>
|
||||||
<string name="download_already_exists">Yükləmə artıq var</string>
|
<string name="download_already_exists">Yükləmə artıq var</string>
|
||||||
<string name="preferred_locale">Üstünlük Verilən Yer</string>
|
<string name="preferred_locale">Üstünlük Verilən Yer</string>
|
||||||
<string name="pause">Dayandır
|
<string name="pause">Dayandır</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Təkrar başlat</string>
|
<string name="resume">Təkrar başlat</string>
|
||||||
<string name="updating_download_data">Yükləmə Element Məlumatı Yenilənir</string>
|
<string name="updating_download_data">Yükləmə Element Məlumatı Yenilənir</string>
|
||||||
<string name="keep_cache">Qalığı Saxla</string>
|
<string name="keep_cache">Qalığı Saxla</string>
|
||||||
|
|
@ -282,7 +281,7 @@
|
||||||
<string name="subtitle_format">Titr Formatı
|
<string name="subtitle_format">Titr Formatı
|
||||||
\n</string>
|
\n</string>
|
||||||
<string name="hide_thumbnails">Miniatürləri Gizlət</string>
|
<string name="hide_thumbnails">Miniatürləri Gizlət</string>
|
||||||
<string name="hide_terminal">Sıxacı paylaşma menyusundan gizlət</string>
|
<string name="show_terminal">Sıxacı paylaşma menyusundan gizlət</string>
|
||||||
<string name="saved">Saxlanıldı</string>
|
<string name="saved">Saxlanıldı</string>
|
||||||
<string name="clear_saved">Saxlanılanları Təmizlə</string>
|
<string name="clear_saved">Saxlanılanları Təmizlə</string>
|
||||||
<string name="use_extra_commands">Əlavə Əmrlər Əlavə Et</string>
|
<string name="use_extra_commands">Əlavə Əmrlər Əlavə Et</string>
|
||||||
|
|
|
||||||
|
|
@ -232,8 +232,7 @@
|
||||||
<string name="quick_download">Schneller Download</string>
|
<string name="quick_download">Schneller Download</string>
|
||||||
<string name="quick_download_summary">Daten nicht vorab abrufen</string>
|
<string name="quick_download_summary">Daten nicht vorab abrufen</string>
|
||||||
<string name="download_already_exists">Download bereits vorhanden</string>
|
<string name="download_already_exists">Download bereits vorhanden</string>
|
||||||
<string name="pause">Pause
|
<string name="pause">Pause</string>
|
||||||
\n</string>
|
|
||||||
<string name="backup">Sicherung</string>
|
<string name="backup">Sicherung</string>
|
||||||
<string name="restore">Wiederherstellen</string>
|
<string name="restore">Wiederherstellen</string>
|
||||||
<string name="network_error">Netzwerkfehler</string>
|
<string name="network_error">Netzwerkfehler</string>
|
||||||
|
|
|
||||||
|
|
@ -221,8 +221,7 @@
|
||||||
<string name="download_now">Λήψη Τώρα</string>
|
<string name="download_now">Λήψη Τώρα</string>
|
||||||
<string name="download_already_exists">Η λήψη υπάρχει ήδη</string>
|
<string name="download_already_exists">Η λήψη υπάρχει ήδη</string>
|
||||||
<string name="preferred_locale">Προτιμώμενες Τοπικές Ρυθμίσεις</string>
|
<string name="preferred_locale">Προτιμώμενες Τοπικές Ρυθμίσεις</string>
|
||||||
<string name="pause">Παύση
|
<string name="pause">Παύση</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Συνέχεια</string>
|
<string name="resume">Συνέχεια</string>
|
||||||
<string name="incognito">Ανώνυμη Λειτουργία</string>
|
<string name="incognito">Ανώνυμη Λειτουργία</string>
|
||||||
<string name="sponsorblock">SponsorBlock</string>
|
<string name="sponsorblock">SponsorBlock</string>
|
||||||
|
|
|
||||||
|
|
@ -236,8 +236,7 @@
|
||||||
<string name="finished_download_notification_channel_name">Descargas terminadas</string>
|
<string name="finished_download_notification_channel_name">Descargas terminadas</string>
|
||||||
<string name="finished_download_notification_channel_description">Notificación de descargas finalizadas o defectuosas</string>
|
<string name="finished_download_notification_channel_description">Notificación de descargas finalizadas o defectuosas</string>
|
||||||
<string name="preferred_locale">Ubicación preferida</string>
|
<string name="preferred_locale">Ubicación preferida</string>
|
||||||
<string name="pause">Pausa
|
<string name="pause">Pausa</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Resumen</string>
|
<string name="resume">Resumen</string>
|
||||||
<string name="updating_download_data">Actualizando los datos de los elementos de la descarga</string>
|
<string name="updating_download_data">Actualizando los datos de los elementos de la descarga</string>
|
||||||
<string name="keep_cache">Conservar la caché</string>
|
<string name="keep_cache">Conservar la caché</string>
|
||||||
|
|
@ -285,7 +284,7 @@
|
||||||
\n</string>
|
\n</string>
|
||||||
<string name="hide_thumbnails">Ocultar las miniaturas</string>
|
<string name="hide_thumbnails">Ocultar las miniaturas</string>
|
||||||
<string name="saved">Guardado</string>
|
<string name="saved">Guardado</string>
|
||||||
<string name="hide_terminal">Ocultar Terminal del menú compartir</string>
|
<string name="show_terminal">Ocultar Terminal del menú compartir</string>
|
||||||
<string name="save_for_later">¿Guardar la descarga para más tarde\?</string>
|
<string name="save_for_later">¿Guardar la descarga para más tarde\?</string>
|
||||||
<string name="clear_saved">Borrar lo Guardado</string>
|
<string name="clear_saved">Borrar lo Guardado</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -153,8 +153,7 @@
|
||||||
<string name="preferred_format_id">पसंदीदा प्रारूप आईडी</string>
|
<string name="preferred_format_id">पसंदीदा प्रारूप आईडी</string>
|
||||||
<string name="download_now">तुरंत डाउनलोड करें</string>
|
<string name="download_now">तुरंत डाउनलोड करें</string>
|
||||||
<string name="preferred_locale">पसंदीदा लोकेल</string>
|
<string name="preferred_locale">पसंदीदा लोकेल</string>
|
||||||
<string name="pause">रोको
|
<string name="pause">रोको</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">चालू करो</string>
|
<string name="resume">चालू करो</string>
|
||||||
<string name="keep_cache">कैचे रखें</string>
|
<string name="keep_cache">कैचे रखें</string>
|
||||||
<string name="keep_cache_summary">डाउनलोड समाप्त होने के बाद अस्थायी फ़ाइलें न हटाएं</string>
|
<string name="keep_cache_summary">डाउनलोड समाप्त होने के बाद अस्थायी फ़ाइलें न हटाएं</string>
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,7 @@
|
||||||
<string name="preferred_format_id">Preferensi ID Format</string>
|
<string name="preferred_format_id">Preferensi ID Format</string>
|
||||||
<string name="download_now">Unduh Sekarang</string>
|
<string name="download_now">Unduh Sekarang</string>
|
||||||
<string name="remove_audio">Hilangkan Audio</string>
|
<string name="remove_audio">Hilangkan Audio</string>
|
||||||
<string name="pause">Jeda
|
<string name="pause">Jeda</string>
|
||||||
\n</string>
|
|
||||||
<string name="updating_download_data">Memutakhirkan Data Butir Unduhan</string>
|
<string name="updating_download_data">Memutakhirkan Data Butir Unduhan</string>
|
||||||
<string name="preferred_locale">Preferensi Wilayah</string>
|
<string name="preferred_locale">Preferensi Wilayah</string>
|
||||||
<string name="resume">Lanjutkan</string>
|
<string name="resume">Lanjutkan</string>
|
||||||
|
|
@ -278,9 +277,8 @@
|
||||||
<string name="format_order">Urutan Format</string>
|
<string name="format_order">Urutan Format</string>
|
||||||
<string name="force_keyframes">Paksakan Keyframe saat Pemotongan</string>
|
<string name="force_keyframes">Paksakan Keyframe saat Pemotongan</string>
|
||||||
<string name="force_keyframes_summary">Proses yang lebih lambat, tetapi pemotongannya lebih akurat</string>
|
<string name="force_keyframes_summary">Proses yang lebih lambat, tetapi pemotongannya lebih akurat</string>
|
||||||
<string name="hide_terminal">Sembunyikan Terminal dari menu berbagi</string>
|
<string name="show_terminal">Sembunyikan Terminal dari menu berbagi</string>
|
||||||
<string name="subtitle_format">Format Takarir (Subtitle)
|
<string name="subtitle_format">Format Takarir (Subtitle)</string>
|
||||||
\n</string>
|
|
||||||
<string name="hide_thumbnails">Sembunyikan Keluku (Thumbnail)</string>
|
<string name="hide_thumbnails">Sembunyikan Keluku (Thumbnail)</string>
|
||||||
<string name="clear_saved">Bersihkan yang Disimpan</string>
|
<string name="clear_saved">Bersihkan yang Disimpan</string>
|
||||||
<string name="saved">Disimpan</string>
|
<string name="saved">Disimpan</string>
|
||||||
|
|
|
||||||
|
|
@ -238,8 +238,7 @@
|
||||||
<string name="quick_download_summary">事前にデータを取得しません</string>
|
<string name="quick_download_summary">事前にデータを取得しません</string>
|
||||||
<string name="remove_audio">音声を削除</string>
|
<string name="remove_audio">音声を削除</string>
|
||||||
<string name="download_already_exists">ダウンロードに既に存在します</string>
|
<string name="download_already_exists">ダウンロードに既に存在します</string>
|
||||||
<string name="pause">一時停止
|
<string name="pause">一時停止</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">再開</string>
|
<string name="resume">再開</string>
|
||||||
<string name="keep_cache">キャッシュを保持</string>
|
<string name="keep_cache">キャッシュを保持</string>
|
||||||
<string name="keep_cache_summary">ダウンロードの完了後に一時ファイルを削除しないようにします</string>
|
<string name="keep_cache_summary">ダウンロードの完了後に一時ファイルを削除しないようにします</string>
|
||||||
|
|
|
||||||
|
|
@ -241,8 +241,7 @@
|
||||||
<string name="system">시스템</string>
|
<string name="system">시스템</string>
|
||||||
<string name="red">빨간색</string>
|
<string name="red">빨간색</string>
|
||||||
<string name="pure_theme_summary">퓨어 블랙 / 화이트 테마</string>
|
<string name="pure_theme_summary">퓨어 블랙 / 화이트 테마</string>
|
||||||
<string name="pause">일시정지
|
<string name="pause">일시정지</string>
|
||||||
\n</string>
|
|
||||||
<string name="material_you">머터리얼</string>
|
<string name="material_you">머터리얼</string>
|
||||||
<string name="green">녹색</string>
|
<string name="green">녹색</string>
|
||||||
<string name="blue">파란색</string>
|
<string name="blue">파란색</string>
|
||||||
|
|
|
||||||
|
|
@ -228,8 +228,7 @@
|
||||||
<string name="preferred_format_id">Vēlamā Formāta ID</string>
|
<string name="preferred_format_id">Vēlamā Formāta ID</string>
|
||||||
<string name="download_now">Lejupielādēt Tagad</string>
|
<string name="download_now">Lejupielādēt Tagad</string>
|
||||||
<string name="download_already_exists">Lejupielāde jau pastāv</string>
|
<string name="download_already_exists">Lejupielāde jau pastāv</string>
|
||||||
<string name="pause">Pauze
|
<string name="pause">Pauze</string>
|
||||||
\n</string>
|
|
||||||
<string name="updating_download_data">Notiek Lejupielādes Vienuma Datu Atjaunināšana</string>
|
<string name="updating_download_data">Notiek Lejupielādes Vienuma Datu Atjaunināšana</string>
|
||||||
<string name="keep_cache">Paturēt Kešatmiņu</string>
|
<string name="keep_cache">Paturēt Kešatmiņu</string>
|
||||||
<string name="keep_cache_summary">Neizdzēst pagaidu failus pēc lejupielādes pabeigšanas</string>
|
<string name="keep_cache_summary">Neizdzēst pagaidu failus pēc lejupielādes pabeigšanas</string>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="pause">Stans
|
<string name="pause">Stans</string>
|
||||||
\n</string>
|
|
||||||
<string name="keep_cache">Behald mellomgøymet</string>
|
<string name="keep_cache">Behald mellomgøymet</string>
|
||||||
<string name="keep_cache_summary">Ikkje slett mellombelse filer etter at hentinga er ferdig</string>
|
<string name="keep_cache_summary">Ikkje slett mellombelse filer etter at hentinga er ferdig</string>
|
||||||
<string name="network_error">Nettverksfeil</string>
|
<string name="network_error">Nettverksfeil</string>
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,7 @@
|
||||||
<string name="download_now">Pobierz teraz</string>
|
<string name="download_now">Pobierz teraz</string>
|
||||||
<string name="download_already_exists">Pobieranie już istnieje</string>
|
<string name="download_already_exists">Pobieranie już istnieje</string>
|
||||||
<string name="preferred_locale">Preferowane ustawienia regionalne</string>
|
<string name="preferred_locale">Preferowane ustawienia regionalne</string>
|
||||||
<string name="pause">Pauza
|
<string name="pause">Pauza</string>
|
||||||
\n</string>
|
|
||||||
<string name="updating_download_data">Aktualizowanie danych elementu do pobrania</string>
|
<string name="updating_download_data">Aktualizowanie danych elementu do pobrania</string>
|
||||||
<string name="keep_cache_summary">Nie usuwaj plików tymczasowych po zakończeniu pobierania</string>
|
<string name="keep_cache_summary">Nie usuwaj plików tymczasowych po zakończeniu pobierania</string>
|
||||||
<string name="restore">Przywróć</string>
|
<string name="restore">Przywróć</string>
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,7 @@
|
||||||
<string name="download_already_exists">O download já existe</string>
|
<string name="download_already_exists">O download já existe</string>
|
||||||
<string name="keep_cache">Manter Cache</string>
|
<string name="keep_cache">Manter Cache</string>
|
||||||
<string name="updating_download_data">Atualizando os dados do item de download</string>
|
<string name="updating_download_data">Atualizando os dados do item de download</string>
|
||||||
<string name="pause">Pausar
|
<string name="pause">Pausar</string>
|
||||||
\n</string>
|
|
||||||
<string name="preferred_locale">Local preferido</string>
|
<string name="preferred_locale">Local preferido</string>
|
||||||
<string name="resume">Continuar</string>
|
<string name="resume">Continuar</string>
|
||||||
<string name="network_error">Erro de rede</string>
|
<string name="network_error">Erro de rede</string>
|
||||||
|
|
@ -278,10 +277,9 @@
|
||||||
<string name="sponsorblock">Bloqueio de Patrocinadores</string>
|
<string name="sponsorblock">Bloqueio de Patrocinadores</string>
|
||||||
<string name="force_keyframes">Forçar quadros-chave nos cortes</string>
|
<string name="force_keyframes">Forçar quadros-chave nos cortes</string>
|
||||||
<string name="force_keyframes_summary">Processo lento, mas cortes mais precisos</string>
|
<string name="force_keyframes_summary">Processo lento, mas cortes mais precisos</string>
|
||||||
<string name="subtitle_format">Formato da Legenda
|
<string name="subtitle_format">Formato da Legenda</string>
|
||||||
\n</string>
|
|
||||||
<string name="hide_thumbnails">Ocultar Miniaturas</string>
|
<string name="hide_thumbnails">Ocultar Miniaturas</string>
|
||||||
<string name="hide_terminal">Ocultar Terminal do menu de compartilhamento</string>
|
<string name="show_terminal">Ocultar Terminal do menu de compartilhamento</string>
|
||||||
<string name="saved">Salvo</string>
|
<string name="saved">Salvo</string>
|
||||||
<string name="clear_saved">Limpar Salvo</string>
|
<string name="clear_saved">Limpar Salvo</string>
|
||||||
<string name="save_for_later">Salvar download para mais tarde\?</string>
|
<string name="save_for_later">Salvar download para mais tarde\?</string>
|
||||||
|
|
|
||||||
|
|
@ -168,8 +168,7 @@
|
||||||
<string name="download_now">Descarregar agora</string>
|
<string name="download_now">Descarregar agora</string>
|
||||||
<string name="download_already_exists">Descarga já existente</string>
|
<string name="download_already_exists">Descarga já existente</string>
|
||||||
<string name="preferred_locale">Idioma preferido</string>
|
<string name="preferred_locale">Idioma preferido</string>
|
||||||
<string name="pause">Pausa
|
<string name="pause">Pausa</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Retomar</string>
|
<string name="resume">Retomar</string>
|
||||||
<string name="keep_cache">Manter em cache</string>
|
<string name="keep_cache">Manter em cache</string>
|
||||||
<string name="backup">Backup</string>
|
<string name="backup">Backup</string>
|
||||||
|
|
|
||||||
|
|
@ -239,8 +239,7 @@
|
||||||
<string name="format_filtering_hint">Чтобы использовать эту опцию, все элементы должны быть одного типа</string>
|
<string name="format_filtering_hint">Чтобы использовать эту опцию, все элементы должны быть одного типа</string>
|
||||||
<string name="restore_complete">Восстановление приложения завершено. Были восстановлены следующие объекты:</string>
|
<string name="restore_complete">Восстановление приложения завершено. Были восстановлены следующие объекты:</string>
|
||||||
<string name="download_already_exists">Загрузка уже существует</string>
|
<string name="download_already_exists">Загрузка уже существует</string>
|
||||||
<string name="pause">Пауза
|
<string name="pause">Пауза</string>
|
||||||
\n</string>
|
|
||||||
<string name="preferred_locale">Предпочтительный регион</string>
|
<string name="preferred_locale">Предпочтительный регион</string>
|
||||||
<string name="video_recommendations">Видеорекомендации</string>
|
<string name="video_recommendations">Видеорекомендации</string>
|
||||||
<string name="couldnt_parse_file">Не удалось разобрать файл</string>
|
<string name="couldnt_parse_file">Не удалось разобрать файл</string>
|
||||||
|
|
@ -284,7 +283,7 @@
|
||||||
<string name="subtitle_format">Формат субтиров
|
<string name="subtitle_format">Формат субтиров
|
||||||
\n</string>
|
\n</string>
|
||||||
<string name="hide_thumbnails">Скрыть миниатюры видео</string>
|
<string name="hide_thumbnails">Скрыть миниатюры видео</string>
|
||||||
<string name="hide_terminal">Скрыть терминал из меню \"Поделиться\"</string>
|
<string name="show_terminal">Скрыть терминал из меню \"Поделиться\"</string>
|
||||||
<string name="saved">Сохраненные</string>
|
<string name="saved">Сохраненные</string>
|
||||||
<string name="clear_saved">Очистить сохраненные</string>
|
<string name="clear_saved">Очистить сохраненные</string>
|
||||||
<string name="save_for_later">Сохранить загрузку для возврата к ней позднее\?</string>
|
<string name="save_for_later">Сохранить загрузку для возврата к ней позднее\?</string>
|
||||||
|
|
|
||||||
|
|
@ -241,8 +241,7 @@
|
||||||
<string name="keep_cache">Mbaj Memoriken Kashe</string>
|
<string name="keep_cache">Mbaj Memoriken Kashe</string>
|
||||||
<string name="keep_cache_summary">Mos fshi skedarët e përkohshëm pasi shkarkimi ka mbaruar</string>
|
<string name="keep_cache_summary">Mos fshi skedarët e përkohshëm pasi shkarkimi ka mbaruar</string>
|
||||||
<string name="restore">Rikthe</string>
|
<string name="restore">Rikthe</string>
|
||||||
<string name="pause">Pauzë
|
<string name="pause">Pauzë</string>
|
||||||
\n</string>
|
|
||||||
<string name="updating_download_data">Duke Përditësuar Informacionet e Objektit</string>
|
<string name="updating_download_data">Duke Përditësuar Informacionet e Objektit</string>
|
||||||
<string name="backup">Ruaj</string>
|
<string name="backup">Ruaj</string>
|
||||||
<string name="select_backup_categories">Zgjidh kategoritë për ruajtje</string>
|
<string name="select_backup_categories">Zgjidh kategoritë për ruajtje</string>
|
||||||
|
|
@ -281,7 +280,7 @@
|
||||||
<string name="force_keyframes_summary">Proçes më i ngadaltë, por prerje më të sakta</string>
|
<string name="force_keyframes_summary">Proçes më i ngadaltë, por prerje më të sakta</string>
|
||||||
<string name="subtitle_format">Formati i Titrave
|
<string name="subtitle_format">Formati i Titrave
|
||||||
\n</string>
|
\n</string>
|
||||||
<string name="hide_terminal">Fshihe Terminalin nga fleta e shpërndarjes</string>
|
<string name="show_terminal">Fshihe Terminalin nga fleta e shpërndarjes</string>
|
||||||
<string name="saved">Të ruajtura</string>
|
<string name="saved">Të ruajtura</string>
|
||||||
<string name="clear_saved">Pastro të ruajturat</string>
|
<string name="clear_saved">Pastro të ruajturat</string>
|
||||||
<string name="save_for_later">Ruaj Shkarkimin për më vonë\?</string>
|
<string name="save_for_later">Ruaj Shkarkimin për më vonë\?</string>
|
||||||
|
|
|
||||||
|
|
@ -240,8 +240,7 @@
|
||||||
<string name="download_now">Şimdi İndir</string>
|
<string name="download_now">Şimdi İndir</string>
|
||||||
<string name="remove_audio">Sesi Kaldır</string>
|
<string name="remove_audio">Sesi Kaldır</string>
|
||||||
<string name="preferred_locale">Tercih Edilen Konum</string>
|
<string name="preferred_locale">Tercih Edilen Konum</string>
|
||||||
<string name="pause">Duraklat
|
<string name="pause">Duraklat</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Devam et</string>
|
<string name="resume">Devam et</string>
|
||||||
<string name="updating_download_data">İndirilen Öğe Verilerini Güncelleme</string>
|
<string name="updating_download_data">İndirilen Öğe Verilerini Güncelleme</string>
|
||||||
<string name="keep_cache">Önbelleği Sakla</string>
|
<string name="keep_cache">Önbelleği Sakla</string>
|
||||||
|
|
|
||||||
|
|
@ -236,8 +236,7 @@
|
||||||
<string name="download_now">Завантажити зараз</string>
|
<string name="download_now">Завантажити зараз</string>
|
||||||
<string name="download_already_exists">Завантаження вже існує</string>
|
<string name="download_already_exists">Завантаження вже існує</string>
|
||||||
<string name="preferred_locale">Бажане розташування</string>
|
<string name="preferred_locale">Бажане розташування</string>
|
||||||
<string name="pause">Пауза
|
<string name="pause">Пауза</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">Продовжити</string>
|
<string name="resume">Продовжити</string>
|
||||||
<string name="updating_download_data">Оновлення даних завантажуваного елемента</string>
|
<string name="updating_download_data">Оновлення даних завантажуваного елемента</string>
|
||||||
<string name="keep_cache">Зберегти кеш</string>
|
<string name="keep_cache">Зберегти кеш</string>
|
||||||
|
|
@ -282,7 +281,7 @@
|
||||||
<string name="current">Поточна команда</string>
|
<string name="current">Поточна команда</string>
|
||||||
<string name="use_extra_commands_summary">Додайте свої додаткові команди перед завантаженням аудіо/відео</string>
|
<string name="use_extra_commands_summary">Додайте свої додаткові команди перед завантаженням аудіо/відео</string>
|
||||||
<string name="hide_thumbnails">Приховати мініатюри відео</string>
|
<string name="hide_thumbnails">Приховати мініатюри відео</string>
|
||||||
<string name="hide_terminal">Приховати термінал з меню \"Поділитися\"</string>
|
<string name="show_terminal">Приховати термінал з меню \"Поділитися\"</string>
|
||||||
<string name="saved">Збережені</string>
|
<string name="saved">Збережені</string>
|
||||||
<string name="clear_saved">Очистити збережені</string>
|
<string name="clear_saved">Очистити збережені</string>
|
||||||
<string name="subtitle_format">Формат субтитрів
|
<string name="subtitle_format">Формат субтитрів
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,7 @@
|
||||||
<string name="download_now">立即下載</string>
|
<string name="download_now">立即下載</string>
|
||||||
<string name="download_already_exists">已存在下載</string>
|
<string name="download_already_exists">已存在下載</string>
|
||||||
<string name="preferred_locale">首選地區設定</string>
|
<string name="preferred_locale">首選地區設定</string>
|
||||||
<string name="pause">暫停
|
<string name="pause">暫停</string>
|
||||||
\n</string>
|
|
||||||
<string name="resume">繼續</string>
|
<string name="resume">繼續</string>
|
||||||
<string name="updating_download_data">正在更新下載項目資料</string>
|
<string name="updating_download_data">正在更新下載項目資料</string>
|
||||||
<string name="keep_cache">保留快取</string>
|
<string name="keep_cache">保留快取</string>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<color name="grey">#323232</color>
|
<color name="grey">#323232</color>
|
||||||
<color name="light_grey">#A6A6A6</color>
|
<color name="light_grey">#A6A6A6</color>
|
||||||
<color name="icon_bg">#FFFFFF</color>
|
<color name="icon_bg">#FFFFFF</color>
|
||||||
<color name="icon_fg">#d43c3c</color>
|
<color name="icon_fg">#db2e2e</color>
|
||||||
|
|
||||||
|
|
||||||
<color name="blue_md_theme_light_primary">#0058CB</color>
|
<color name="blue_md_theme_light_primary">#0058CB</color>
|
||||||
|
|
@ -320,9 +320,9 @@
|
||||||
<color name="orange_md_theme_dark_errorContainer">#93000A</color>
|
<color name="orange_md_theme_dark_errorContainer">#93000A</color>
|
||||||
<color name="orange_md_theme_dark_onError">#690005</color>
|
<color name="orange_md_theme_dark_onError">#690005</color>
|
||||||
<color name="orange_md_theme_dark_onErrorContainer">#FFDAD6</color>
|
<color name="orange_md_theme_dark_onErrorContainer">#FFDAD6</color>
|
||||||
<color name="orange_md_theme_dark_background">#1F1B16</color>
|
<color name="orange_md_theme_dark_background">#1b1b1b</color>
|
||||||
<color name="orange_md_theme_dark_onBackground">#EBE1D9</color>
|
<color name="orange_md_theme_dark_onBackground">#EBE1D9</color>
|
||||||
<color name="orange_md_theme_dark_surface">#1F1B16</color>
|
<color name="orange_md_theme_dark_surface">#1b1b1b</color>
|
||||||
<color name="orange_md_theme_dark_onSurface">#EBE1D9</color>
|
<color name="orange_md_theme_dark_onSurface">#EBE1D9</color>
|
||||||
<color name="orange_md_theme_dark_surfaceVariant">#504539</color>
|
<color name="orange_md_theme_dark_surfaceVariant">#504539</color>
|
||||||
<color name="orange_md_theme_dark_onSurfaceVariant">#D4C4B5</color>
|
<color name="orange_md_theme_dark_onSurfaceVariant">#D4C4B5</color>
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@
|
||||||
<string name="download_now">Download Now</string>
|
<string name="download_now">Download Now</string>
|
||||||
<string name="download_already_exists">Download already exists</string>
|
<string name="download_already_exists">Download already exists</string>
|
||||||
<string name="preferred_locale">Preferred Locale</string>
|
<string name="preferred_locale">Preferred Locale</string>
|
||||||
<string name="pause">Pause\n</string>
|
<string name="pause">Pause</string>
|
||||||
<string name="resume">Resume</string>
|
<string name="resume">Resume</string>
|
||||||
<string name="updating_download_data">Updating Download Item Data</string>
|
<string name="updating_download_data">Updating Download Item Data</string>
|
||||||
<string name="keep_cache">Keep Cache</string>
|
<string name="keep_cache">Keep Cache</string>
|
||||||
|
|
@ -290,7 +290,7 @@
|
||||||
<string name="current">Current Command</string>
|
<string name="current">Current Command</string>
|
||||||
<string name="subtitle_format">Subtitle Format\n</string>
|
<string name="subtitle_format">Subtitle Format\n</string>
|
||||||
<string name="hide_thumbnails">Hide Thumbnails</string>
|
<string name="hide_thumbnails">Hide Thumbnails</string>
|
||||||
<string name="hide_terminal">Hide Terminal from share menu</string>
|
<string name="show_terminal">Show Terminal in share menu</string>
|
||||||
<string name="saved">Saved</string>
|
<string name="saved">Saved</string>
|
||||||
<string name="clear_saved">Clear Saved</string>
|
<string name="clear_saved">Clear Saved</string>
|
||||||
<string name="save_for_later">Save Download for Later?</string>
|
<string name="save_for_later">Save Download for Later?</string>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
app:title="@string/socks5_proxy" />
|
app:title="@string/socks5_proxy" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:dependency="download_card"
|
|
||||||
android:defaultValue="video"
|
android:defaultValue="video"
|
||||||
android:entries="@array/download_types"
|
android:entries="@array/download_types"
|
||||||
android:entryValues="@array/download_types_values"
|
android:entryValues="@array/download_types_values"
|
||||||
|
|
|
||||||
|
|
@ -112,9 +112,9 @@
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:widgetLayout="@layout/preferece_material_switch"
|
android:widgetLayout="@layout/preferece_material_switch"
|
||||||
app:defaultValue="true"
|
app:defaultValue="false"
|
||||||
android:icon="@drawable/baseline_share_24"
|
android:icon="@drawable/baseline_share_24"
|
||||||
android:key="hide_terminal"
|
android:key="show_terminal"
|
||||||
app:title="@string/hide_terminal" />
|
app:title="@string/show_terminal" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Loading…
Reference in a new issue