forked from recloudstream/cloudstream
download UI fixes
This commit is contained in:
parent
fa399cd350
commit
a1165344d3
10 changed files with 248 additions and 294 deletions
|
@ -168,8 +168,8 @@ object CommonActivity {
|
||||||
Aria2Settings(
|
Aria2Settings(
|
||||||
"1337", //UUID.randomUUID().toString()
|
"1337", //UUID.randomUUID().toString()
|
||||||
4337,
|
4337,
|
||||||
act.filesDir.path, //"/storage/emulated/0/Download",//
|
act.filesDir.path + "/download", //"/storage/emulated/0/Download",//
|
||||||
"${act.filesDir.path}/session"
|
null//"${act.filesDir.path}/session"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,10 @@ object Aria2cHelper {
|
||||||
VideoDownloadManager.downloadDeleteEvent.invoke(id.toInt())
|
VideoDownloadManager.downloadDeleteEvent.invoke(id.toInt())
|
||||||
|
|
||||||
getMetadata(id)?.let { data ->
|
getMetadata(id)?.let { data ->
|
||||||
Aria2Starter.deleteFiles(data.items.flatMap { it.files })
|
Aria2Starter.delete(
|
||||||
|
DownloadListener.sessionIdToGid[id],
|
||||||
|
id,
|
||||||
|
data.items.flatMap { it.files })
|
||||||
}
|
}
|
||||||
removeMetadata(id)
|
removeMetadata(id)
|
||||||
AcraApplication.removeKey(KEY_DOWNLOAD_INFO, id.toString())
|
AcraApplication.removeKey(KEY_DOWNLOAD_INFO, id.toString())
|
||||||
|
|
|
@ -2,23 +2,160 @@ package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.text.format.Formatter
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.view.doOnAttach
|
||||||
|
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
||||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||||
|
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import com.lagradost.fetchbutton.aria2c.Aria2Starter
|
import com.lagradost.fetchbutton.aria2c.DownloadListener
|
||||||
|
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
||||||
|
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
|
|
||||||
object DownloadButtonSetup {
|
object DownloadButtonSetup {
|
||||||
|
fun bind(
|
||||||
|
card: IVisualDownloadChildCached,
|
||||||
|
downloadButton: PieFetchButton,
|
||||||
|
extraInfo: TextView,
|
||||||
|
clickCallback: (DownloadClickEvent) -> Unit
|
||||||
|
) {
|
||||||
|
val d = card.data ?: return
|
||||||
|
|
||||||
|
fun updateText(downloadBytes: Long, totalBytes: Long) {
|
||||||
|
extraInfo?.apply {
|
||||||
|
text =
|
||||||
|
context.getString(R.string.download_size_format).format(
|
||||||
|
Formatter.formatShortFileSize(context, downloadBytes),
|
||||||
|
Formatter.formatShortFileSize(context, totalBytes)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateText(card.currentBytes, card.totalBytes)
|
||||||
|
downloadButton.apply {
|
||||||
|
val play =
|
||||||
|
if (card is VisualDownloadChildCached) R.string.play_episode else R.string.play_movie_button//if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode
|
||||||
|
|
||||||
|
setPersistentId(d.id.toLong())
|
||||||
|
doOnAttach { view ->
|
||||||
|
view.findViewTreeLifecycleOwner()?.let { life ->
|
||||||
|
DownloadListener.observe(life) {
|
||||||
|
gid?.let { realGId ->
|
||||||
|
val meta = DownloadListener.getInfo(realGId)
|
||||||
|
updateText(meta.downloadedLength, meta.totalLength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isValid = when (downloadButton.currentStatus) {
|
||||||
|
null, DownloadStatusTell.Removed -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
downloadButton.setOnClickListener {
|
||||||
|
val view = downloadButton
|
||||||
|
|
||||||
|
fun delete() {
|
||||||
|
// view.deleteAllFiles()
|
||||||
|
clickCallback.invoke(
|
||||||
|
DownloadClickEvent(
|
||||||
|
DOWNLOAD_ACTION_DELETE_FILE,
|
||||||
|
d
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (view !is PieFetchButton) return@setOnClickListener
|
||||||
|
when (view.currentStatus) {
|
||||||
|
/*null, DownloadStatusTell.Removed -> {
|
||||||
|
view.setStatus(DownloadStatusTell.Waiting)
|
||||||
|
downloadClickCallback.invoke(
|
||||||
|
DownloadEpisodeClickEvent(
|
||||||
|
DOWNLOAD_ACTION_DOWNLOAD,
|
||||||
|
card
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
DownloadStatusTell.Paused -> {
|
||||||
|
view.popupMenuNoIcons(
|
||||||
|
if (isValid) listOf(
|
||||||
|
1 to R.string.resume,
|
||||||
|
2 to play,
|
||||||
|
3 to R.string.delete
|
||||||
|
) else listOf(2 to play, 3 to R.string.delete)
|
||||||
|
) {
|
||||||
|
when (itemId) {
|
||||||
|
1 -> if (!view.resumeDownload()) {
|
||||||
|
/*downloadClickCallback.invoke(
|
||||||
|
DownloadEpisodeClickEvent(
|
||||||
|
DOWNLOAD_ACTION_DOWNLOAD,
|
||||||
|
card
|
||||||
|
)
|
||||||
|
)*/
|
||||||
|
}
|
||||||
|
2 -> play(d)
|
||||||
|
3 -> delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DownloadStatusTell.Complete -> {
|
||||||
|
view.popupMenuNoIcons(
|
||||||
|
listOf(
|
||||||
|
2 to play,
|
||||||
|
3 to R.string.delete
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
when (itemId) {
|
||||||
|
2 -> play(d)
|
||||||
|
3 -> delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DownloadStatusTell.Active -> {
|
||||||
|
view.popupMenuNoIcons(
|
||||||
|
if (isValid) listOf(
|
||||||
|
4 to R.string.pause,
|
||||||
|
2 to play,
|
||||||
|
3 to R.string.delete
|
||||||
|
) else listOf(
|
||||||
|
2 to play,
|
||||||
|
3 to R.string.delete
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
when (itemId) {
|
||||||
|
4 -> view.pauseDownload()
|
||||||
|
2 -> play(d)
|
||||||
|
3 -> delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DownloadStatusTell.Error -> {
|
||||||
|
view.redownload()
|
||||||
|
}
|
||||||
|
DownloadStatusTell.Waiting -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun handleDownloadClick(activity: Activity?, click: DownloadClickEvent) {
|
fun handleDownloadClick(activity: Activity?, click: DownloadClickEvent) {
|
||||||
val id = click.data.id
|
val id = click.data.id
|
||||||
if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return
|
if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return
|
||||||
|
@ -90,7 +227,8 @@ object DownloadButtonSetup {
|
||||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
||||||
act,
|
act,
|
||||||
click.data.id
|
click.data.id
|
||||||
)?.fileLength ?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength
|
)?.fileLength
|
||||||
|
?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength
|
||||||
?: 0
|
?: 0
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
showToast(act, R.string.delete, Toast.LENGTH_LONG)
|
showToast(act, R.string.delete, Toast.LENGTH_LONG)
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
import android.text.format.Formatter
|
|
||||||
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.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.view.doOnAttach
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
||||||
|
@ -17,10 +14,7 @@ import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.fetchbutton.aria2c.DownloadListener
|
|
||||||
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
|
||||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
||||||
|
|
||||||
|
@ -31,11 +25,17 @@ const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3
|
||||||
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
||||||
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
||||||
|
|
||||||
|
interface IVisualDownloadChildCached{
|
||||||
|
val currentBytes: Long
|
||||||
|
val totalBytes: Long
|
||||||
|
val data: VideoDownloadHelper.DownloadEpisodeCached?
|
||||||
|
}
|
||||||
|
|
||||||
data class VisualDownloadChildCached(
|
data class VisualDownloadChildCached(
|
||||||
val currentBytes: Long,
|
override val currentBytes: Long,
|
||||||
val totalBytes: Long,
|
override val totalBytes: Long,
|
||||||
val data: VideoDownloadHelper.DownloadEpisodeCached,
|
override val data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||||
)
|
) : IVisualDownloadChildCached
|
||||||
|
|
||||||
data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData)
|
data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData)
|
||||||
data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||||
|
@ -97,124 +97,8 @@ class DownloadChildAdapter(
|
||||||
title.text = title.context.getNameFull(d.name, d.episode, d.season)
|
title.text = title.context.getNameFull(d.name, d.episode, d.season)
|
||||||
title.isSelected = true // is needed for text repeating
|
title.isSelected = true // is needed for text repeating
|
||||||
//extraInfo.text = card.currentBytes
|
//extraInfo.text = card.currentBytes
|
||||||
|
DownloadButtonSetup.bind(card, downloadButton, extraInfo, clickCallback)
|
||||||
|
|
||||||
fun updateText(downloadBytes: Long, totalBytes: Long) {
|
|
||||||
extraInfo?.apply {
|
|
||||||
text =
|
|
||||||
context.getString(R.string.download_size_format).format(
|
|
||||||
Formatter.formatShortFileSize(context, downloadBytes),
|
|
||||||
Formatter.formatShortFileSize(context, totalBytes)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateText(card.currentBytes, card.totalBytes)
|
|
||||||
|
|
||||||
downloadButton.apply {
|
|
||||||
val play =
|
|
||||||
R.string.play_episode//if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode
|
|
||||||
|
|
||||||
setPersistentId(d.id.toLong())
|
|
||||||
doOnAttach { view ->
|
|
||||||
view.findViewTreeLifecycleOwner()?.let { life ->
|
|
||||||
DownloadListener.observe(life) {
|
|
||||||
gid?.let { realGId ->
|
|
||||||
val meta = DownloadListener.getInfo(realGId)
|
|
||||||
updateText(meta.downloadedLength, meta.totalLength)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadButton.isVisible = when (downloadButton.currentStatus) {
|
|
||||||
null, DownloadStatusTell.Removed -> false
|
|
||||||
else -> true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
downloadButton.setOnClickListener {
|
|
||||||
val view = downloadButton
|
|
||||||
|
|
||||||
fun delete() {
|
|
||||||
// view.deleteAllFiles()
|
|
||||||
clickCallback.invoke(
|
|
||||||
DownloadClickEvent(
|
|
||||||
DOWNLOAD_ACTION_DELETE_FILE,
|
|
||||||
d
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (view !is PieFetchButton) return@setOnClickListener
|
|
||||||
when (view.currentStatus) {
|
|
||||||
/*null, DownloadStatusTell.Removed -> {
|
|
||||||
view.setStatus(DownloadStatusTell.Waiting)
|
|
||||||
downloadClickCallback.invoke(
|
|
||||||
DownloadEpisodeClickEvent(
|
|
||||||
DOWNLOAD_ACTION_DOWNLOAD,
|
|
||||||
card
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}*/
|
|
||||||
DownloadStatusTell.Paused -> {
|
|
||||||
view.popupMenuNoIcons(
|
|
||||||
listOf(
|
|
||||||
1 to R.string.resume,
|
|
||||||
2 to play,
|
|
||||||
3 to R.string.delete
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
when (itemId) {
|
|
||||||
1 -> if (!view.resumeDownload()) {
|
|
||||||
/*downloadClickCallback.invoke(
|
|
||||||
DownloadEpisodeClickEvent(
|
|
||||||
DOWNLOAD_ACTION_DOWNLOAD,
|
|
||||||
card
|
|
||||||
)
|
|
||||||
)*/
|
|
||||||
}
|
|
||||||
2 -> play(d)
|
|
||||||
3 -> delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DownloadStatusTell.Complete -> {
|
|
||||||
view.popupMenuNoIcons(
|
|
||||||
listOf(
|
|
||||||
2 to play,
|
|
||||||
3 to R.string.delete
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
when (itemId) {
|
|
||||||
2 -> play(d)
|
|
||||||
3 -> delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DownloadStatusTell.Active -> {
|
|
||||||
view.popupMenuNoIcons(
|
|
||||||
listOf(
|
|
||||||
4 to R.string.pause,
|
|
||||||
2 to play,
|
|
||||||
3 to R.string.delete
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
when (itemId) {
|
|
||||||
4 -> view.pauseDownload()
|
|
||||||
2 -> play(d)
|
|
||||||
3 -> delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DownloadStatusTell.Error -> {
|
|
||||||
view.redownload()
|
|
||||||
}
|
|
||||||
DownloadStatusTell.Waiting -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
if (downloadButton.isVisible) {
|
if (downloadButton.isVisible) {
|
||||||
downloadButton.play(d)
|
downloadButton.play(d)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||||
|
@ -41,7 +42,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
): View? {
|
): View? {
|
||||||
return inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
return inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
private var hasPopped = false // fix stupid bug
|
||||||
private fun updateList(folder: String) = main {
|
private fun updateList(folder: String) = main {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
||||||
|
@ -54,8 +55,10 @@ class DownloadChildFragment : Fragment() {
|
||||||
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
||||||
}
|
}
|
||||||
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
||||||
if (eps.isEmpty()) {
|
|
||||||
activity?.onBackPressed()
|
if (eps.isEmpty() && !hasPopped) {
|
||||||
|
hasPopped = true
|
||||||
|
activity?.popCurrentPage()
|
||||||
return@main
|
return@main
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,6 @@ class DownloadFragment : Fragment() {
|
||||||
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
||||||
downloadDeleteEventListener = null
|
downloadDeleteEventListener = null
|
||||||
}
|
}
|
||||||
(download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
|
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +164,7 @@ class DownloadFragment : Fragment() {
|
||||||
downloadDeleteEventListener = { id ->
|
downloadDeleteEventListener = { id ->
|
||||||
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
if (list.any { it.data.id == id }) {
|
if (list.any { it.data?.id == id }) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
setList(ArrayList())
|
setList(ArrayList())
|
||||||
downloadsViewModel.updateList(ctx)
|
downloadsViewModel.updateList(ctx)
|
||||||
|
|
|
@ -8,23 +8,25 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class VisualDownloadHeaderCached(
|
data class VisualDownloadHeaderCached(
|
||||||
val currentOngoingDownloads: Int,
|
val currentOngoingDownloads: Int,
|
||||||
val totalDownloads: Int,
|
val totalDownloads: Int,
|
||||||
val totalBytes: Long,
|
override val totalBytes: Long,
|
||||||
val currentBytes: Long,
|
override val currentBytes: Long,
|
||||||
val data: VideoDownloadHelper.DownloadHeaderCached,
|
val header: VideoDownloadHelper.DownloadHeaderCached,
|
||||||
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
override val data: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||||
)
|
) : IVisualDownloadChildCached
|
||||||
|
|
||||||
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
||||||
|
|
||||||
|
@ -34,35 +36,6 @@ class DownloadHeaderAdapter(
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
|
|
||||||
private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? {
|
|
||||||
return Collections.unmodifiableSet(mBoundViewHolders)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun killAdapter() {
|
|
||||||
getAllBoundViewHolders()?.forEach { view ->
|
|
||||||
view?.downloadButton?.dispose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
|
||||||
if (holder is DownloadButtonViewHolder) {
|
|
||||||
holder.downloadButton.dispose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
|
||||||
if (holder is DownloadButtonViewHolder) {
|
|
||||||
holder.downloadButton.dispose()
|
|
||||||
mBoundViewHolders.remove(holder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
|
||||||
if (holder is DownloadButtonViewHolder) {
|
|
||||||
holder.reattachDownloadButton()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return DownloadHeaderViewHolder(
|
return DownloadHeaderViewHolder(
|
||||||
|
@ -76,7 +49,6 @@ class DownloadHeaderAdapter(
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is DownloadHeaderViewHolder -> {
|
is DownloadHeaderViewHolder -> {
|
||||||
holder.bind(cardList[position])
|
holder.bind(cardList[position])
|
||||||
mBoundViewHolders.add(holder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,23 +62,17 @@ class DownloadHeaderAdapter(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
override var downloadButton = EasyDownloadButton()
|
|
||||||
|
|
||||||
private val poster: ImageView? = itemView.download_header_poster
|
private val poster: ImageView? = itemView.download_header_poster
|
||||||
private val title: TextView = itemView.download_header_title
|
private val title: TextView = itemView.download_header_title
|
||||||
private val extraInfo: TextView = itemView.download_header_info
|
private val extraInfo: TextView = itemView.download_header_info
|
||||||
private val holder: CardView = itemView.episode_holder
|
private val holder: CardView = itemView.episode_holder
|
||||||
|
|
||||||
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
|
private val downloadButton: PieFetchButton = itemView.download_header_download
|
||||||
private val downloadImage: ImageView = itemView.download_header_episode_download
|
|
||||||
private val normalImage: ImageView = itemView.download_header_goto_child
|
|
||||||
private var localCard: VisualDownloadHeaderCached? = null
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: VisualDownloadHeaderCached) {
|
fun bind(card: VisualDownloadHeaderCached) {
|
||||||
localCard = card
|
val d = card.header
|
||||||
val d = card.data
|
|
||||||
|
|
||||||
poster?.setImage(d.poster)
|
poster?.setImage(d.poster)
|
||||||
poster?.setOnClickListener {
|
poster?.setOnClickListener {
|
||||||
|
@ -117,10 +83,8 @@ class DownloadHeaderAdapter(
|
||||||
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
||||||
|
|
||||||
//val isMovie = d.type.isMovieType()
|
//val isMovie = d.type.isMovieType()
|
||||||
if (card.child != null) {
|
if (card.data != null) {
|
||||||
downloadBar.visibility = View.VISIBLE
|
downloadButton.isVisible = true
|
||||||
downloadImage.visibility = View.VISIBLE
|
|
||||||
normalImage.visibility = View.GONE
|
|
||||||
/*setUpButton(
|
/*setUpButton(
|
||||||
card.currentBytes,
|
card.currentBytes,
|
||||||
card.totalBytes,
|
card.totalBytes,
|
||||||
|
@ -130,14 +94,15 @@ class DownloadHeaderAdapter(
|
||||||
card.child,
|
card.child,
|
||||||
movieClickCallback
|
movieClickCallback
|
||||||
)*/
|
)*/
|
||||||
|
DownloadButtonSetup.bind(card, downloadButton, extraInfo) { click ->
|
||||||
|
movieClickCallback.invoke(DownloadClickEvent(click.action, card.data))
|
||||||
|
}
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.data))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
downloadBar.visibility = View.GONE
|
downloadButton.isVisible = false
|
||||||
downloadImage.visibility = View.GONE
|
|
||||||
normalImage.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
extraInfo.text =
|
extraInfo.text =
|
||||||
|
@ -160,21 +125,5 @@ class DownloadHeaderAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reattachDownloadButton() {
|
|
||||||
downloadButton.dispose()
|
|
||||||
val card = localCard
|
|
||||||
if (card?.child != null) {
|
|
||||||
downloadButton.setUpButton(
|
|
||||||
card.currentBytes,
|
|
||||||
card.totalBytes,
|
|
||||||
downloadBar,
|
|
||||||
downloadImage,
|
|
||||||
extraInfo,
|
|
||||||
card.child,
|
|
||||||
movieClickCallback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ class DownloadViewModel : ViewModel() {
|
||||||
.distinctBy { it.id } // Remove duplicates
|
.distinctBy { it.id } // Remove duplicates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("CHILDRE:$children")
|
||||||
|
|
||||||
// parentId : bytes
|
// parentId : bytes
|
||||||
val totalBytesUsedByChild = HashMap<Int, Long>()
|
val totalBytesUsedByChild = HashMap<Int, Long>()
|
||||||
// parentId : bytes
|
// parentId : bytes
|
||||||
|
@ -69,7 +71,8 @@ class DownloadViewModel : ViewModel() {
|
||||||
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println("FIXED: $totalDownloads")
|
println("TotalDownloads:$totalDownloads")
|
||||||
|
//println("FIXED: $totalDownloads")
|
||||||
val cached = withContext(Dispatchers.IO) { // wont fetch useless keys
|
val cached = withContext(Dispatchers.IO) { // wont fetch useless keys
|
||||||
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
||||||
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
||||||
|
@ -78,6 +81,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println("Cached:$cached")
|
||||||
|
|
||||||
val visual = withContext(Dispatchers.IO) {
|
val visual = withContext(Dispatchers.IO) {
|
||||||
cached.mapNotNull { // TODO FIX
|
cached.mapNotNull { // TODO FIX
|
||||||
|
@ -100,7 +104,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
movieEpisode
|
movieEpisode
|
||||||
)
|
)
|
||||||
}.sortedBy {
|
}.sortedBy {
|
||||||
(it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0)
|
(it.data?.episode ?: 0) + (it.data?.season?.times(10000) ?: 0)
|
||||||
} // episode sorting by episode, lowest to highest
|
} // episode sorting by episode, lowest to highest
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -530,6 +530,7 @@ object VideoDownloadManager {
|
||||||
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
|
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
|
||||||
projection, selection, null, null
|
projection, selection, null, null
|
||||||
)
|
)
|
||||||
|
println("result:$result ${result?.count}")
|
||||||
|
|
||||||
result.use { c ->
|
result.use { c ->
|
||||||
if (c != null && c.count >= 1) {
|
if (c != null && c.count >= 1) {
|
||||||
|
@ -1505,21 +1506,31 @@ object VideoDownloadManager {
|
||||||
|
|
||||||
private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? {
|
private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? {
|
||||||
try {
|
try {
|
||||||
|
println("getDownloadFileInfo:$id")
|
||||||
|
|
||||||
val info =
|
val info =
|
||||||
context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return null
|
context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return null
|
||||||
val base = basePathToFile(context, info.basePath)
|
val base = basePathToFile(context, info.basePath)
|
||||||
|
println("BASE:$info")
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) {
|
||||||
val cr = context.contentResolver ?: return null
|
val cr = context.contentResolver ?: return null
|
||||||
|
println("CR:$cr")
|
||||||
|
|
||||||
val fileUri =
|
val fileUri =
|
||||||
cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName)
|
cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName)
|
||||||
?: return null
|
?: return null
|
||||||
|
println("FILEURI:$fileUri")
|
||||||
|
|
||||||
val fileLength = cr.getFileLength(fileUri) ?: return null
|
val fileLength = cr.getFileLength(fileUri) ?: return null
|
||||||
|
println("fileLength:$fileLength")
|
||||||
|
|
||||||
if (fileLength == 0L) return null
|
if (fileLength == 0L) return null
|
||||||
return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri)
|
return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri)
|
||||||
} else {
|
} else {
|
||||||
|
println("STUFF:$base")
|
||||||
|
|
||||||
val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName)
|
val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName)
|
||||||
|
println("file:$file")
|
||||||
|
|
||||||
// val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName)
|
// val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName)
|
||||||
// val dFile = File(normalPath)
|
// val dFile = File(normalPath)
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView 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/episode_holder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
|
||||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
|
||||||
android:id="@+id/episode_holder"
|
|
||||||
android:foreground="@drawable/outline_drawable"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginTop="10dp">
|
android:foreground="@drawable/outline_drawable"
|
||||||
|
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||||
|
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:orientation="horizontal"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
|
android:orientation="horizontal">
|
||||||
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="70dp"
|
android:layout_width="70dp"
|
||||||
|
@ -24,80 +24,43 @@
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/download_header_poster"
|
android:id="@+id/download_header_poster"
|
||||||
tools:src="@drawable/example_poster"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:contentDescription="@string/episode_poster_img_des" />
|
android:contentDescription="@string/episode_poster_img_des"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
tools:src="@drawable/example_poster" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginEnd="70dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_header_title"
|
android:id="@+id/download_header_title"
|
||||||
tools:text="Perfect Run"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="?attr/textColor"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="Perfect Run" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_header_info"
|
android:id="@+id/download_header_info"
|
||||||
tools:text="1 episode | 285MB"
|
|
||||||
android:textColor="?attr/grayTextColor"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_marginStart="-50dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:padding="50dp"
|
|
||||||
android:layout_width="50dp"
|
|
||||||
android:id="@+id/download_header_goto_child"
|
|
||||||
android:layout_gravity="center_vertical|end"
|
|
||||||
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
|
|
||||||
android:contentDescription="@string/download" />
|
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_marginStart="-50dp"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:id="@+id/download_header_progress_downloaded"
|
|
||||||
android:indeterminate="false"
|
|
||||||
android:progressDrawable="@drawable/circular_progress_bar_cs3"
|
|
||||||
android:background="@drawable/circle_shape_cs3"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:max="100"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:progress="0"
|
|
||||||
android:visibility="visible" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:visibility="visible"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="10dp"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:layout_width="50dp"
|
tools:text="1 episode | 285MB" />
|
||||||
android:id="@+id/download_header_episode_download"
|
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
|
||||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
|
||||||
android:contentDescription="@string/download"
|
|
||||||
app:tint="?attr/white" />
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
|
android:id="@+id/download_header_download"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_gravity="center_vertical|end"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:padding="10dp" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
Loading…
Reference in a new issue