Merge branch 'main' into weblate-ytdlnis-strings
This commit is contained in:
commit
f309f0813b
67 changed files with 881 additions and 434 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">Sichern</string>
|
<string name="backup">Sichern</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,8 +277,7 @@
|
||||||
<string name="sponsorblock">Bloqueio do Patrocinador</string>
|
<string name="sponsorblock">Bloqueio do Patrocinador</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 mais lento, mas cortes mais precisos</string>
|
<string name="force_keyframes_summary">Processo mais 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="hide_terminal">Ocultar Terminal do menu de compartilhamento</string>
|
||||||
<string name="saved">Salvou</string>
|
<string name="saved">Salvou</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>
|
||||||
|
|
@ -281,8 +280,7 @@
|
||||||
<string name="use_extra_commands_summary">Добавьте свои дополнительные команды перед загрузкой аудио/видео</string>
|
<string name="use_extra_commands_summary">Добавьте свои дополнительные команды перед загрузкой аудио/видео</string>
|
||||||
<string name="use_extra_commands">Дополнительные команды</string>
|
<string name="use_extra_commands">Дополнительные команды</string>
|
||||||
<string name="current">Текущая команда</string>
|
<string name="current">Текущая команда</string>
|
||||||
<string name="subtitle_format">Формат субтитров
|
<string name="subtitle_format">Формат субтитров</string>
|
||||||
\n</string>
|
|
||||||
<string name="hide_thumbnails">Скрыть миниатюры</string>
|
<string name="hide_thumbnails">Скрыть миниатюры</string>
|
||||||
<string name="hide_terminal">Скрыть терминал из меню «Поделиться»</string>
|
<string name="hide_terminal">Скрыть терминал из меню «Поделиться»</string>
|
||||||
<string name="saved">Сохранено</string>
|
<string name="saved">Сохранено</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>
|
||||||
|
|
|
||||||
|
|
@ -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