added download multiple card

This commit is contained in:
Denis Çerri 2023-01-25 16:41:16 +01:00
parent a6b078f95b
commit ff58bd2dbf
No known key found for this signature in database
GPG key ID: 95C43D517D830350
15 changed files with 379 additions and 253 deletions

View file

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 1, "version": 1,
"identityHash": "2c0fdec170ca54d97ef928dfe28a6992", "identityHash": "db5c9df3e43ddd5a5131bbd372a7c92b",
"entities": [ "entities": [
{ {
"tableName": "results", "tableName": "results",
@ -74,7 +74,7 @@
}, },
{ {
"tableName": "formats", "tableName": "formats",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `itemId` INTEGER NOT NULL, `format_id` TEXT NOT NULL, `container` TEXT NOT NULL, `filesize` INTEGER NOT NULL, `format_note` TEXT NOT NULL, `encoding` TEXT NOT NULL)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `itemId` INTEGER NOT NULL, `format_id` TEXT NOT NULL, `container` TEXT NOT NULL, `filesize` INTEGER NOT NULL, `format_note` TEXT NOT NULL)",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -111,12 +111,6 @@
"columnName": "format_note", "columnName": "format_note",
"affinity": "TEXT", "affinity": "TEXT",
"notNull": true "notNull": true
},
{
"fieldPath": "encoding",
"columnName": "encoding",
"affinity": "TEXT",
"notNull": true
} }
], ],
"primaryKey": { "primaryKey": {
@ -392,7 +386,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2c0fdec170ca54d97ef928dfe28a6992')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'db5c9df3e43ddd5a5131bbd372a7c92b')"
] ]
} }
} }

View file

@ -19,7 +19,9 @@
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" > android:enableOnBackInvokedCallback="true"
android:theme="@style/AppTheme"
tools:targetApi="tiramisu">
<activity android:name=".MainActivity" <activity android:name=".MainActivity"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:exported="true"> android:exported="true">

View file

@ -4,10 +4,12 @@ import android.app.Activity
import android.graphics.Color import android.graphics.Color
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.AsyncDifferConfig import androidx.recyclerview.widget.AsyncDifferConfig
@ -16,12 +18,13 @@ 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.models.ResultItem
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
ListAdapter<DownloadItem?, ConfigureMultipleDownloadsAdapter.ViewHolder?>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
private val onItemClickListener: OnItemClickListener private val onItemClickListener: OnItemClickListener
private val activity: Activity private val activity: Activity
@ -30,18 +33,17 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
this.activity = activity this.activity = activity
} }
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
RecyclerView.ViewHolder(itemView) {
val cardView: MaterialCardView val cardView: MaterialCardView
init { init {
cardView = itemView.findViewById(R.id.download_multiple_card_view) cardView = itemView.findViewById(R.id.download_card_view)
} }
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val cardView = LayoutInflater.from(parent.context) val cardView = LayoutInflater.from(parent.context)
.inflate(R.layout.home_download_multiple_card, parent, false) .inflate(R.layout.download_card, parent, false)
return ViewHolder(cardView, onItemClickListener) return ViewHolder(cardView, onItemClickListener)
} }
@ -49,7 +51,7 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
val item = getItem(position) val item = getItem(position)
val card = holder.cardView val card = holder.cardView
// THUMBNAIL ---------------------------------- // THUMBNAIL ----------------------------------
val thumbnail = card.findViewById<ImageView>(R.id.result_image_view) val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
val imageURL = item!!.thumb val imageURL = item!!.thumb
if (imageURL.isNotEmpty()) { if (imageURL.isNotEmpty()) {
val uiHandler = Handler(Looper.getMainLooper()) val uiHandler = Handler(Looper.getMainLooper())
@ -62,7 +64,7 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
} }
// TITLE ---------------------------------- // TITLE ----------------------------------
val itemTitle = card.findViewById<TextView>(R.id.result_title) val itemTitle = card.findViewById<TextView>(R.id.title)
var title = item.title var title = item.title
if (title.length > 100) { if (title.length > 100) {
title = title.substring(0, 40) + "..." title = title.substring(0, 40) + "..."
@ -73,20 +75,16 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
val author = card.findViewById<TextView>(R.id.author) val author = card.findViewById<TextView>(R.id.author)
author.text = item.author author.text = item.author
// Format // Container ----------------------------------
val format = card.findViewById<TextView>(R.id.format) val container = card.findViewById<TextView>(R.id.container)
format.text = item.ext container.text = item.ext
// Quality
val quality = card.findViewById<TextView>(R.id.quality)
quality.text = item.formatDesc
// File Size // File Size
val fileSize = card.findViewById<TextView>(R.id.filesize) val fileSize = card.findViewById<TextView>(R.id.filesize)
fileSize.text = item.filesize fileSize.text = item.filesize
// Type Icon Button // Type Icon Button
val btn = card.findViewById<MaterialButton>(R.id.download_type) val btn = card.findViewById<MaterialButton>(R.id.downloads_download_button_type)
when(item.type) { when(item.type) {
"audio" -> { "audio" -> {
@ -105,21 +103,20 @@ class ConfigureMultipleDownloadsAdapter(onItemClickListener: OnItemClickListener
} }
} }
interface OnItemClickListener { interface OnItemClickListener {
fun onButtonClick(videoURL: String, type: String?)
fun onCardClick(itemID: Long) fun onCardClick(itemID: Long)
} }
companion object { companion object {
private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = private val DIFF_CALLBACK: DiffUtil.ItemCallback<DownloadItem> = object : DiffUtil.ItemCallback<DownloadItem>() {
object : DiffUtil.ItemCallback<DownloadItem>() { override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
override fun areItemsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean { return oldItem.id === newItem.id
return oldItem.id === newItem.id
}
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
return oldItem.url == newItem.url
}
} }
override fun areContentsTheSame(oldItem: DownloadItem, newItem: DownloadItem): Boolean {
return oldItem.url == newItem.url && oldItem.title == newItem.title && oldItem.author == newItem.author
}
}
} }
} }

View file

@ -9,14 +9,17 @@ import com.deniscerri.ytdlnis.util.FileUtil
@Dao @Dao
interface DownloadDao { interface DownloadDao {
@Query("SELECT * FROM downloads") @Query("SELECT * FROM downloads ORDER BY status")
fun getAllDownloads() : LiveData<List<DownloadItem>> fun getAllDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Active'") @Query("SELECT * FROM downloads WHERE status='Active'")
fun getActiveDownloads() : LiveData<List<DownloadItem>> fun getActiveDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Queued'") @Query("SELECT * FROM downloads WHERE status='Queued'")
fun getQueuedDownloads() : List<DownloadItem> fun getQueuedDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Processing'")
fun getProcessingDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE workID=:workID") @Query("SELECT * FROM downloads WHERE workID=:workID")
fun getDownloadByWorkId(workID: Int) : DownloadItem fun getDownloadByWorkId(workID: Int) : DownloadItem
@ -33,6 +36,9 @@ interface DownloadDao {
@Delete @Delete
suspend fun delete(item: DownloadItem) suspend fun delete(item: DownloadItem)
@Query("DELETE FROM downloads WHERE status='Processing'")
suspend fun deleteProcessing()
@Update(onConflict = OnConflictStrategy.REPLACE) @Update(onConflict = OnConflictStrategy.REPLACE)
suspend fun update(item: DownloadItem) suspend fun update(item: DownloadItem)

View file

@ -7,16 +7,14 @@ import com.google.gson.annotations.SerializedName
@Entity(tableName = "formats") @Entity(tableName = "formats")
data class Format( data class Format(
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
var id: Long, var id: Long = -1,
var itemId: Long, var itemId: Long = 0,
@SerializedName(value = "format_id", alternate = ["itag"]) @SerializedName(value = "format_id", alternate = ["itag"])
val format_id: String, val format_id: String = "",
@SerializedName(value = "ext", alternate = ["container"]) @SerializedName(value = "ext", alternate = ["container"])
val container: String, val container: String = "",
@SerializedName(value = "filesize", alternate = ["clen", "filesize_approx"]) @SerializedName(value = "filesize", alternate = ["clen", "filesize_approx"])
val filesize: Long, val filesize: Long = 0,
@SerializedName(value = "format_note", alternate = ["resolution", "audioQuality"]) @SerializedName(value = "format_note", alternate = ["resolution", "audioQuality"])
val format_note: String, val format_note: String = ""
@SerializedName(value = "encoding", alternate = ["vcodec", "acodec", "video_ext"])
val encoding: String
) )

View file

@ -3,11 +3,16 @@ package com.deniscerri.ytdlnis.database.repository
import android.util.Log import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.deniscerri.ytdlnis.database.dao.DownloadDao import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.dao.FormatDao
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.ResultItem
class DownloadRepository(private val downloadDao: DownloadDao) { class DownloadRepository(private val downloadDao: DownloadDao) {
val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads() val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads()
val activeDownloads : LiveData<List<DownloadItem>> = downloadDao.getActiveDownloads() val activeDownloads : LiveData<List<DownloadItem>> = downloadDao.getActiveDownloads()
val queuedDownloads : LiveData<List<DownloadItem>> = downloadDao.getQueuedDownloads()
val processingDownloads : LiveData<List<DownloadItem>> = downloadDao.getProcessingDownloads()
enum class status { enum class status {
Active, Queued, Errored, Processing Active, Queued, Errored, Processing
@ -29,9 +34,6 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
return downloadDao.getDownloadByWorkId(workID) return downloadDao.getDownloadByWorkId(workID)
} }
fun getQueuedDownloads() : List<DownloadItem>{
return downloadDao.getQueuedDownloads()
}
suspend fun setDownloadStatus(item: DownloadItem, status: status){ suspend fun setDownloadStatus(item: DownloadItem, status: status){
item.status = status.toString() item.status = status.toString()
@ -42,4 +44,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
return downloadDao.getDownloadById(id) return downloadDao.getDownloadById(id)
} }
suspend fun deleteProcessing(){
downloadDao.deleteProcessing()
}
} }

View file

@ -1,24 +1,35 @@
package com.deniscerri.ytdlnis.database.viewmodel package com.deniscerri.ytdlnis.database.viewmodel
import android.app.Activity
import android.app.Application import android.app.Application
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.App
import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.models.DownloadItem import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class DownloadViewModel(application: Application) : AndroidViewModel(application) { class DownloadViewModel(application: Application) : AndroidViewModel(application) {
private val repository : DownloadRepository private val repository : DownloadRepository
private val allDownloads : LiveData<List<DownloadItem>> val allDownloads : LiveData<List<DownloadItem>>
val queuedDownloads : LiveData<List<DownloadItem>>
val activeDownloads : LiveData<List<DownloadItem>>
val processingDownloads : LiveData<List<DownloadItem>>
init { init {
val dao = DBManager.getInstance(application).downloadDao val dao = DBManager.getInstance(application).downloadDao
val formatDao = DBManager.getInstance(application).formatDao
repository = DownloadRepository(dao) repository = DownloadRepository(dao)
allDownloads = repository.allDownloads allDownloads = repository.allDownloads
queuedDownloads = repository.queuedDownloads
activeDownloads = repository.activeDownloads
processingDownloads = repository.processingDownloads
} }
fun startWork(items: List<DownloadItem>){ fun startWork(items: List<DownloadItem>){
@ -48,4 +59,51 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
fun getItemByID(id: Long) : DownloadItem { fun getItemByID(id: Long) : DownloadItem {
return repository.getItemByID(id) return repository.getItemByID(id)
} }
fun createDownloadItemFromResult(resultItem: ResultItem, type: String) : DownloadItem {
val sharedPreferences =
getApplication<App>().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
return DownloadItem(0,
resultItem.url,
resultItem.title,
resultItem.author,
resultItem.thumb,
resultItem.duration,
type,
"", "", 0, "", false,
"", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, "",
"", DownloadRepository.status.Processing.toString(), 0
)
}
fun turnResultItemstoDownloadItems(items: List<ResultItem?>) : List<DownloadItem> {
val list : MutableList<DownloadItem> = mutableListOf()
items.forEach {
list.add(createDownloadItemFromResult(it!!, "video"))
}
return list
}
fun putDownloadsForProcessing(items: List<ResultItem?>) : LiveData<List<Long>> {
val result = MutableLiveData<List<Long>>()
viewModelScope.launch(Dispatchers.IO){
val list : MutableList<Long> = mutableListOf()
items.forEachIndexed { i, it ->
val tmpDownloadItem = createDownloadItemFromResult(it!!, "video")
val id = repository.insert(tmpDownloadItem)
list.add(id)
}
result.postValue(list)
}
return result
}
fun deleteProcessing() = viewModelScope.launch(Dispatchers.IO) {
repository.deleteProcessing()
}
} }

View file

@ -10,6 +10,7 @@ import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.dao.FormatDao import com.deniscerri.ytdlnis.database.dao.FormatDao
import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdlnis.database.models.Format
import com.deniscerri.ytdlnis.database.models.ResultItem import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.repository.ResultRepository import com.deniscerri.ytdlnis.database.repository.ResultRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -111,7 +112,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
"video" -> { "video" -> {
list = list.filter { !it.format_note.contains("audio", ignoreCase = true) } list = list.filter { !it.format_note.contains("audio", ignoreCase = true) }
if (list.isEmpty()) { if (list.isEmpty()) {
videoFormats.forEach { formats.add(Format(0, item.id, it, "", 0, it, "")) } videoFormats.forEach { formats.add(Format(0, item.id, it, "", 0, it)) }
return formats return formats
} }
return list return list
@ -120,7 +121,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
val templates = repository.getTemplates() val templates = repository.getTemplates()
templates.forEach { templates.forEach {
formats.add(Format(0, item.id, it.title, "", 0, it.content, "")) formats.add(Format(0, item.id, it.title, "", 0, it.content))
} }
return formats return formats
} }

View file

@ -6,13 +6,13 @@ import java.util.*
class DownloadInfo { class DownloadInfo {
var video: ResultItem? = null var video: ResultItem? = null
var progress = 0 var progress = 0
var downloadQueue: LinkedList<ResultItem>? = null //var downloadQueue: LinkedList<ResultItem>? = null
var outputLine: String? = null var outputLine: String? = null
var downloadStatus: String? = null var downloadStatus: String? = null
var downloadPath: String? = null var downloadPath: String? = null
var downloadType: String? = null var downloadType: String? = null
fun setDownloadQueue(downloadQueue: LinkedList<ResultItem>) { // fun setDownloadQueue(downloadQueue: LinkedList<ResultItem>) {
this.downloadQueue = downloadQueue // this.downloadQueue = downloadQueue
video = downloadQueue.peek() // video = downloadQueue.peek()
} // }
} }

View file

@ -23,13 +23,16 @@ import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.adapter.HomeAdapter import com.deniscerri.ytdlnis.adapter.HomeAdapter
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.ResultItem import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.database.models.ResultItemWithFormats
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.database.viewmodel.ResultViewModel import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.service.DownloadInfo import com.deniscerri.ytdlnis.service.DownloadInfo
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.util.FileUtil import com.deniscerri.ytdlnis.util.FileUtil
import com.deniscerri.ytdlnis.util.InfoUtil import com.deniscerri.ytdlnis.util.InfoUtil
import com.facebook.shimmer.ShimmerFrameLayout import com.facebook.shimmer.ShimmerFrameLayout
@ -42,6 +45,7 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator import com.google.android.material.progressindicator.LinearProgressIndicator
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener { class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
private var progressBar: LinearProgressIndicator? = null private var progressBar: LinearProgressIndicator? = null
@ -166,12 +170,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
homeFabs = view.findViewById(R.id.home_fabs) homeFabs = view.findViewById(R.id.home_fabs)
downloadFabs = homeFabs!!.findViewById(R.id.download_selected_coordinator) downloadFabs = homeFabs!!.findViewById(R.id.download_selected_coordinator)
downloadAllFabCoordinator = homeFabs!!.findViewById(R.id.download_all_coordinator) downloadAllFabCoordinator = homeFabs!!.findViewById(R.id.download_all_coordinator)
val musicFab = downloadFabs!!.findViewById<FloatingActionButton>(R.id.audio_fab) val downloadSelectedFab = downloadFabs!!.findViewById<ExtendedFloatingActionButton>(R.id.download_selected_fab)
val videoFab = downloadFabs!!.findViewById<FloatingActionButton>(R.id.video_fab) downloadSelectedFab.tag = "downloadSelected"
musicFab.tag = "SELECT##audio" downloadSelectedFab.setOnClickListener(this)
videoFab.tag = "SELECT##video"
musicFab.setOnClickListener(this)
videoFab.setOnClickListener(this)
val downloadAllFab = val downloadAllFab =
downloadAllFabCoordinator!!.findViewById<ExtendedFloatingActionButton>(R.id.download_all_fab) downloadAllFabCoordinator!!.findViewById<ExtendedFloatingActionButton>(R.id.download_all_fab)
downloadAllFab.tag = "downloadAll" downloadAllFab.tag = "downloadAll"
@ -359,25 +360,11 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
} }
private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){ private fun showSingleDownloadSheet(resultItem : ResultItem, type: String){
val sharedPreferences = val item = ResultItemWithFormats(
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) resultItem,
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false) resultViewModel.getFormats(resultItem, "video") as ArrayList<Format>
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
val downloadItem = DownloadItem(0,
resultItem.url,
resultItem.title,
resultItem.author,
resultItem.thumb,
resultItem.duration,
type,
"", "", 0, "", false,
"", resultItem.website, "", resultItem.playlistTitle, embedSubs, addChapters, saveThumb, "",
"", DownloadRepository.status.Processing.toString(), 0
) )
val downloadItem = downloadViewModel.createDownloadItemFromResult(resultItem, "video")
downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) { downloadViewModel.insertDownload(downloadItem).observe(viewLifecycleOwner) {
downloadItem.id = it downloadItem.id = it
val bottomSheet = DownloadBottomSheetDialog(downloadItem) val bottomSheet = DownloadBottomSheetDialog(downloadItem)
@ -428,51 +415,27 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
override fun onClick(v: View) { override fun onClick(v: View) {
val viewIdName: String = try { val viewIdName: String = try {
v.tag.toString() v.tag.toString()
} catch (e: Exception) { } catch (e: Exception) {""}
""
}
if (viewIdName.isNotEmpty()) { if (viewIdName.isNotEmpty()) {
if (viewIdName.contains("audio") || viewIdName.contains("video")) { if (viewIdName == "downloadSelected") {
val buttonData = val downloadList = downloadViewModel.turnResultItemstoDownloadItems(selectedObjects!!)
viewIdName.split("##".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() downloadViewModel.putDownloadsForProcessing(selectedObjects!!).observe(viewLifecycleOwner) {
if (buttonData[0] == "SELECT") { it.forEachIndexed { i, itemID ->
initSelectedDownload(buttonData[1]) downloadList[i].id = itemID
}
val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList)
bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
} }
} }
if (viewIdName == "downloadAll") { if (viewIdName == "downloadAll") {
// //remove previously selected val downloadList = downloadViewModel.turnResultItemstoDownloadItems(resultsList!!)
// for (i in selectedObjects!!.indices) { downloadViewModel.putDownloadsForProcessing(resultsList!!).observe(viewLifecycleOwner) {
// val vid = findVideo( it.forEachIndexed { i, itemID ->
// selectedObjects!![i].url downloadList[i].id = itemID
// ) }
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid)) val bottomSheet = DownloadMultipleBottomSheetDialog(downloadList)
// } bottomSheet.show(parentFragmentManager, "downloadMultipleSheet")
// selectedObjects = ArrayList() }
// downloadFabs!!.visibility = GONE
// bottomSheet = BottomSheetDialog(fragmentContext!!)
// bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
// bottomSheet!!.setContentView(R.layout.home_download_all_bottom_sheet)
// val first = bottomSheet!!.findViewById<TextInputLayout>(R.id.first_textinput)
// first!!.editText!!.setText(1.toString())
// val last = bottomSheet!!.findViewById<TextInputLayout>(R.id.last_textinput)
// last!!.editText!!.setText(resultsList!!.size.toString())
// val audio = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_audio_button)
// audio!!.setOnClickListener {
// val start = first.editText!!.text.toString().toInt()
// val end = last.editText!!.text.toString().toInt()
// initDownloadAll(bottomSheet!!, start, end, "audio")
// }
// val video = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_video_button)
// video!!.setOnClickListener {
// val start = first.editText!!.text.toString().toInt()
// val end = last.editText!!.text.toString().toInt()
// initDownloadAll(bottomSheet!!, start, end, "video")
// }
// bottomSheet!!.show()
// bottomSheet!!.window!!.setLayout(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT
// )
} }
} }
} }
@ -518,31 +481,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
// } // }
} }
private fun initSelectedDownload(type: String) {
// val sharedPreferences =
// context!!.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
// val editor = sharedPreferences.edit()
// if (sharedPreferences.getBoolean("download_card", true)) {
// showConfigureDownloadCard(type)
// } else {
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
// }
}
companion object { companion object {
private const val TAG = "HomeFragment" private const val TAG = "HomeFragment"
} }

View file

@ -0,0 +1,127 @@
package com.deniscerri.ytdlnis.ui.downloadcard
import android.annotation.SuppressLint
import android.app.Dialog
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.findFragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.adapter.ConfigureMultipleDownloadsAdapter
import com.deniscerri.ytdlnis.adapter.HomeAdapter
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton
import com.google.android.material.tabs.TabLayout
class DownloadMultipleBottomSheetDialog(private val items: List<DownloadItem>) : BottomSheetDialogFragment(), ConfigureMultipleDownloadsAdapter.OnItemClickListener, View.OnClickListener {
private lateinit var downloadViewModel: DownloadViewModel
private lateinit var listAdapter : ConfigureMultipleDownloadsAdapter
private lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
downloadViewModel = ViewModelProvider(this)[DownloadViewModel::class.java]
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val behavior = BottomSheetBehavior.from(view.parent as View)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
@SuppressLint("RestrictedApi")
override fun setupDialog(dialog: Dialog, style: Int) {
super.setupDialog(dialog, style)
val view = LayoutInflater.from(context).inflate(R.layout.download_multiple_bottom_sheet, null)
dialog.setContentView(view)
view.minimumHeight = resources.displayMetrics.heightPixels
listAdapter =
ConfigureMultipleDownloadsAdapter(
this,
requireActivity()
)
recyclerView = view.findViewById(R.id.downloadMultipleRecyclerview)
recyclerView.layoutManager = LinearLayoutManager(requireContext())
recyclerView.setHasFixedSize(true)
recyclerView.adapter = listAdapter
downloadViewModel.processingDownloads.observe(this) {
listAdapter.submitList(it)
if (it.isEmpty()){
dismiss()
}
}
val cancelBtn = view.findViewById<MaterialButton>(R.id.bottomsheet_cancel_button)
cancelBtn.setOnClickListener{
dismiss()
}
val download = view.findViewById<Button>(R.id.bottomsheet_download_button)
download!!.setOnClickListener {
// for (i in selectedObjects!!.indices) {
// val vid = findVideo(
// selectedObjects!![i]!!.getURL()
// )
// vid!!.downloadedType = type
// updateDownloadingStatusOnResult(vid, type, true)
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
// downloadQueue!!.add(vid)
// }
// selectedObjects = ArrayList()
// homeAdapter!!.clearCheckedVideos()
// downloadFabs!!.visibility = View.GONE
// if (isStoragePermissionGranted) {
// mainActivity!!.startDownloadService(downloadQueue, listener)
// downloadQueue!!.clear()
// }
dismiss()
}
}
override fun onCancel(dialog: DialogInterface) {
super.onCancel(dialog)
cleanDownloads()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
cleanDownloads()
}
private fun cleanDownloads(){
parentFragmentManager.beginTransaction().remove(parentFragmentManager.findFragmentByTag("downloadMultipleSheet")!!).commit()
downloadViewModel.deleteProcessing()
}
override fun onButtonClick(videoURL: String, type: String?) {
TODO("Not yet implemented")
}
override fun onCardClick(itemID: Long) {
TODO("Not yet implemented")
}
override fun onClick(p0: View?) {
TODO("Not yet implemented")
}
}

View file

@ -177,10 +177,9 @@ class DownloadWorker(
YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line -> YoutubeDL.getInstance().execute(request, downloadItem.id.toString()){ progress, _, line ->
setProgressAsync(workDataOf("progress" to progress.toInt())) setProgressAsync(workDataOf("progress" to progress.toInt()))
val title: String = downloadItem.title val title: String = downloadItem.title
val queue = dao.getQueuedDownloads()
notificationUtil.updateDownloadNotification( notificationUtil.updateDownloadNotification(
workID, workID,
line, progress.toInt(), queue.size, title, line, progress.toInt(), 0, title,
NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID NotificationUtil.DOWNLOAD_SERVICE_CHANNEL_ID
) )
} }

View file

@ -1,36 +1,37 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/downloads_card_constraintLayout" android:id="@+id/downloads_card_constraintLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
> >
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/materialButton" android:id="@+id/materialButton"
style="@style/Widget.Material3.Button.IconButton" style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content" android:layout_width="28dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:gravity="end" android:gravity="end"
android:padding="0dp" android:padding="0dp"
app:icon="@drawable/ic_handle" /> app:icon="@drawable/ic_handle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/download_card_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/download_card_view" android:id="@+id/download_card_view"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="95dp" android:layout_height="100dp"
android:layout_margin="10dp" android:layout_margin="10dp"
android:checkable="true" android:checkable="true"
app:cardCornerRadius="10dp" app:cardCornerRadius="10dp"
app:cardElevation="10dp"
app:cardMaxElevation="12dp" app:cardMaxElevation="12dp"
app:cardPreventCornerOverlap="true" app:cardPreventCornerOverlap="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/materialButton"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp"> app:strokeWidth="0dp">
@ -55,60 +56,59 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <LinearLayout
android:id="@+id/title" android:id="@+id/title_author"
android:layout_width="296dp" android:layout_width="300dp"
android:layout_height="41dp" android:layout_height="70dp"
android:paddingStart="10dp" android:orientation="vertical"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="2"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type" app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="2"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
<TextView
android:id="@+id/author"
android:layout_width="296dp"
android:layout_height="23dp"
android:gravity="bottom"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:id="@+id/author"
android:layout_width="296dp"
android:layout_height="23dp"
android:gravity="bottom"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="5dp"
android:shadowColor="@color/black"
android:shadowDx="4"
android:shadowDy="4"
android:shadowRadius="1.5"
android:textColor="@color/white"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/downloads_download_button_type"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title" />
<TextView <TextView
android:id="@+id/container" android:id="@+id/container"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="5dp" android:padding="5dp"
android:text="Mp4"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/filesize"
app:layout_constraintTop_toBottomOf="@+id/author" app:layout_constraintTop_toBottomOf="@+id/downloads_download_button_type" />
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="@+id/encoding"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/container" />
<TextView <TextView
android:id="@+id/filesize" android:id="@+id/filesize"
@ -116,7 +116,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="5dp" android:padding="5dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/encoding" /> app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/downloads_download_button_type" android:id="@+id/downloads_download_button_type"
@ -124,15 +124,16 @@
android:layout_width="55dp" android:layout_width="55dp"
android:layout_height="55dp" android:layout_height="55dp"
android:layout_margin="10dp" android:layout_margin="10dp"
android:layout_marginEnd="8dp"
app:cornerRadius="10dp" app:cornerRadius="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.155" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,16 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="10dp"> android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView <TextView
android:id="@+id/bottom_sheet_title" android:id="@+id/bottom_sheet_title"
@ -48,22 +52,44 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/download_multiple_recyclerview" android:id="@+id/coordinatorLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/constraintLayout">
<RelativeLayout
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/downloadMultipleRecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="150dp"
android:focusableInTouchMode="true"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<LinearLayout <LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:orientation="horizontal"
android:padding="10dp" android:padding="10dp"
android:orientation="horizontal"> app:layout_constraintBottom_toBottomOf="parent">
<Button <Button
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:id="@+id/bottomsheet_schedule_button" android:id="@+id/bottomsheet_schedule_button"
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
@ -77,25 +103,25 @@
android:orientation="horizontal"> android:orientation="horizontal">
<Button <Button
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:id="@+id/bottomsheet_cancel_button" android:id="@+id/bottomsheet_cancel_button"
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/cancel"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:text="@string/cancel"
app:icon="@drawable/ic_cancel" /> app:icon="@drawable/ic_cancel" />
<Button <Button
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:id="@+id/bottomsheet_download_button" android:id="@+id/bottomsheet_download_button"
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autoLink="all"
android:text="@string/download" android:text="@string/download"
app:icon="@drawable/ic_down" app:icon="@drawable/ic_down" />
android:autoLink="all"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -122,42 +122,16 @@
android:visibility="gone" android:visibility="gone"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.cardview.widget.CardView <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/download_selected_fab"
app:elevation="0dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
app:cardCornerRadius="20dp"
android:layout_margin="16dp" android:layout_margin="16dp"
> app:icon="@drawable/ic_down"
android:text="@string/download"
<LinearLayout app:srcCompat="@drawable/ic_music"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/colorPrimaryContainer"
android:orientation="horizontal">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/audio_fab"
app:elevation="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="5dp"
app:srcCompat="@drawable/ic_music"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/video_fab"
app:elevation="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginLeft="5dp"
app:srcCompat="@drawable/ic_video"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>