forked from recloudstream/cloudstream
download stuff
This commit is contained in:
parent
472a9d678a
commit
3606d1ec05
8 changed files with 321 additions and 93 deletions
|
@ -0,0 +1,195 @@
|
|||
package com.lagradost.cloudstream3.ui.download
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.widget.ContentLoadingProgressBar
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||
import com.lagradost.cloudstream3.ui.player.UriData
|
||||
import com.lagradost.cloudstream3.utils.Coroutines
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
|
||||
object DownloadButtonSetup {
|
||||
fun handleDownloadClick(activity: Activity?, headerName: String?, click: DownloadClickEvent) {
|
||||
val id = click.data.id
|
||||
when (click.action) {
|
||||
DOWNLOAD_ACTION_DELETE_FILE -> {
|
||||
activity?.let { ctx ->
|
||||
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
||||
}
|
||||
}
|
||||
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
||||
)
|
||||
}
|
||||
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
||||
activity?.let { ctx ->
|
||||
val pkg = VideoDownloadManager.getDownloadResumePackage(ctx, id)
|
||||
if (pkg != null) {
|
||||
VideoDownloadManager.downloadFromResume(ctx, pkg)
|
||||
} else {
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Resume)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
DOWNLOAD_ACTION_PLAY_FILE -> {
|
||||
activity?.let { act ->
|
||||
val info =
|
||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(act, click.data.id)
|
||||
?: return
|
||||
|
||||
(act as FragmentActivity).supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.enter_anim,
|
||||
R.anim.exit_anim,
|
||||
R.anim.pop_enter,
|
||||
R.anim.pop_exit
|
||||
)
|
||||
.add(
|
||||
R.id.homeRoot,
|
||||
PlayerFragment.newInstance(
|
||||
UriData(
|
||||
info.path.toString(),
|
||||
click.data.id,
|
||||
headerName ?: "null",
|
||||
click.data.episode,
|
||||
click.data.season
|
||||
),
|
||||
act.getViewPos(click.data.id)?.position ?: 0
|
||||
)
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setUpButton(
|
||||
setupCurrentBytes: Long?,
|
||||
setupTotalBytes: Long?,
|
||||
progressBar: ContentLoadingProgressBar,
|
||||
downloadImage: ImageView,
|
||||
textView: TextView?,
|
||||
data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||
clickCallback: (DownloadClickEvent) -> Unit,
|
||||
) {
|
||||
var lastState: VideoDownloadManager.DownloadType? = null
|
||||
var currentBytes = setupCurrentBytes ?: 0
|
||||
var totalBytes = setupTotalBytes ?: 0
|
||||
var needImageUpdate = false
|
||||
|
||||
fun changeDownloadImage(state: VideoDownloadManager.DownloadType) {
|
||||
Coroutines.runOnMainThread {
|
||||
lastState = state
|
||||
if (currentBytes <= 0) needImageUpdate = true
|
||||
val img = if (currentBytes > 0) when (state) {
|
||||
VideoDownloadManager.DownloadType.IsPaused -> R.drawable.ic_baseline_play_arrow_24
|
||||
VideoDownloadManager.DownloadType.IsDownloading -> R.drawable.netflix_pause
|
||||
else -> R.drawable.ic_baseline_delete_outline_24
|
||||
} else R.drawable.netflix_download
|
||||
downloadImage?.setImageResource(img)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun fixDownloadedBytes(setCurrentBytes: Long, setTotalBytes: Long, animate: Boolean) {
|
||||
Coroutines.runOnMainThread {
|
||||
currentBytes = setCurrentBytes
|
||||
totalBytes = setTotalBytes
|
||||
|
||||
if (currentBytes == 0L) {
|
||||
changeDownloadImage(VideoDownloadManager.DownloadType.IsStopped)
|
||||
textView?.visibility = View.GONE
|
||||
progressBar?.visibility = View.GONE
|
||||
} else {
|
||||
if (lastState == VideoDownloadManager.DownloadType.IsStopped) {
|
||||
changeDownloadImage(VideoDownloadManager.getDownloadState(data.id))
|
||||
}
|
||||
textView?.visibility = View.VISIBLE
|
||||
progressBar?.visibility = View.VISIBLE
|
||||
val currentMbString = "%.1f".format(setCurrentBytes / 1000000f)
|
||||
val totalMbString = "%.1f".format(setTotalBytes / 1000000f)
|
||||
|
||||
textView?.text =
|
||||
"${currentMbString}MB / ${totalMbString}MB"
|
||||
|
||||
progressBar?.let { bar ->
|
||||
bar.max = (setTotalBytes / 1000).toInt()
|
||||
|
||||
if (animate) {
|
||||
val animation: ObjectAnimator = ObjectAnimator.ofInt(
|
||||
bar,
|
||||
"progress",
|
||||
bar.progress,
|
||||
(setCurrentBytes / 1000).toInt()
|
||||
)
|
||||
animation.duration = 500
|
||||
animation.setAutoCancel(true)
|
||||
animation.interpolator = DecelerateInterpolator()
|
||||
animation.start()
|
||||
} else {
|
||||
bar.progress = (setCurrentBytes / 1000).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixDownloadedBytes(currentBytes, totalBytes, false)
|
||||
changeDownloadImage(VideoDownloadManager.getDownloadState(data.id))
|
||||
|
||||
VideoDownloadManager.downloadProgressEvent += { downloadData ->
|
||||
if (data.id == downloadData.first) {
|
||||
if (downloadData.second != currentBytes || downloadData.third != totalBytes) { // TO PREVENT WASTING UI TIME
|
||||
fixDownloadedBytes(downloadData.second, downloadData.third, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VideoDownloadManager.downloadStatusEvent += { downloadData ->
|
||||
if (data.id == downloadData.first) {
|
||||
if (lastState != downloadData.second || needImageUpdate) { // TO PREVENT WASTING UI TIME
|
||||
changeDownloadImage(downloadData.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
downloadImage.setOnClickListener {
|
||||
if (currentBytes <= 0) {
|
||||
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data))
|
||||
} else {
|
||||
val list = arrayListOf(
|
||||
Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file),
|
||||
)
|
||||
|
||||
// DON'T RESUME A DOWNLOADED FILE
|
||||
if (lastState != VideoDownloadManager.DownloadType.IsDone && ((currentBytes * 100 / totalBytes) < 98)) {
|
||||
list.add(
|
||||
if (lastState == VideoDownloadManager.DownloadType.IsDownloading)
|
||||
Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download)
|
||||
else
|
||||
Pair(DOWNLOAD_ACTION_RESUME_DOWNLOAD, R.string.popup_resume_download)
|
||||
)
|
||||
}
|
||||
|
||||
it.popupMenuNoIcons(
|
||||
list
|
||||
) {
|
||||
clickCallback.invoke(DownloadClickEvent(itemId, data))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
|||
const val DOWNLOAD_ACTION_DELETE_FILE = 1
|
||||
const val DOWNLOAD_ACTION_RESUME_DOWNLOAD = 2
|
||||
const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3
|
||||
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
||||
|
||||
data class VisualDownloadChildCached(
|
||||
val currentBytes: Long,
|
||||
|
@ -89,6 +90,16 @@ class DownloadChildAdapter(
|
|||
}
|
||||
|
||||
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
|
||||
DownloadButtonSetup.setUpButton(
|
||||
card.currentBytes,
|
||||
card.totalBytes,
|
||||
progressBarDownload,
|
||||
downloadImage,
|
||||
extraInfo,
|
||||
card.data,
|
||||
clickCallback
|
||||
)
|
||||
/*
|
||||
val totalMbString = "%.1f".format(card.totalBytes / 1000000f)
|
||||
|
||||
var lastState: VideoDownloadManager.DownloadType? = null
|
||||
|
@ -175,7 +186,7 @@ class DownloadChildAdapter(
|
|||
) {
|
||||
clickCallback.invoke(DownloadClickEvent(itemId, d))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||
import com.lagradost.cloudstream3.ui.player.UriData
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
|
@ -35,63 +36,6 @@ class DownloadChildFragment : Fragment() {
|
|||
putString("name", headerName)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleDownloadClick(activity: Activity?, headerName: String?, click: DownloadClickEvent) {
|
||||
val id = click.data.id
|
||||
when (click.action) {
|
||||
DOWNLOAD_ACTION_DELETE_FILE -> {
|
||||
activity?.let { ctx ->
|
||||
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
||||
}
|
||||
}
|
||||
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
||||
)
|
||||
}
|
||||
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
||||
activity?.let { ctx ->
|
||||
val pkg = VideoDownloadManager.getDownloadResumePackage(ctx, id)
|
||||
if (pkg != null) {
|
||||
VideoDownloadManager.downloadFromResume(ctx, pkg)
|
||||
} else {
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Resume)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
DOWNLOAD_ACTION_PLAY_FILE -> {
|
||||
activity?.let { act ->
|
||||
val info =
|
||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(act, click.data.id)
|
||||
?: return
|
||||
|
||||
(act as FragmentActivity).supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.anim.enter_anim,
|
||||
R.anim.exit_anim,
|
||||
R.anim.pop_enter,
|
||||
R.anim.pop_exit
|
||||
)
|
||||
.add(
|
||||
R.id.homeRoot,
|
||||
PlayerFragment.newInstance(
|
||||
UriData(
|
||||
info.path.toString(),
|
||||
click.data.id,
|
||||
headerName ?: "null",
|
||||
click.data.episode,
|
||||
click.data.season
|
||||
),
|
||||
act.getViewPos(click.data.id)?.position ?: 0
|
||||
)
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
|
|
|
@ -12,6 +12,11 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import kotlinx.android.synthetic.main.result_episode.view.episode_holder
|
||||
import kotlinx.android.synthetic.main.result_episode.view.episode_text
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.*
|
||||
|
@ -37,8 +42,9 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
|||
|
||||
class EpisodeAdapter(
|
||||
var cardList: List<ResultEpisode>,
|
||||
val hasDownloadSupport : Boolean,
|
||||
private val hasDownloadSupport: Boolean,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) :
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
@LayoutRes
|
||||
|
@ -57,7 +63,8 @@ class EpisodeAdapter(
|
|||
return CardViewHolder(
|
||||
LayoutInflater.from(parent.context).inflate(layout, parent, false),
|
||||
hasDownloadSupport,
|
||||
clickCallback
|
||||
clickCallback,
|
||||
downloadClickCallback
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -76,15 +83,18 @@ class EpisodeAdapter(
|
|||
class CardViewHolder
|
||||
constructor(
|
||||
itemView: View,
|
||||
private val hasDownloadSupport : Boolean,
|
||||
private val hasDownloadSupport: Boolean,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
private val episodeText: TextView = itemView.episode_text
|
||||
private val episodeRating: TextView? = itemView.episode_rating
|
||||
private val episodeDescript: TextView? = itemView.episode_descript
|
||||
private val episodeProgress: ContentLoadingProgressBar? = itemView.episode_progress
|
||||
private val episodePoster: ImageView? = itemView.episode_poster
|
||||
private val episodeDownload: ImageView? = itemView.episode_download
|
||||
|
||||
private val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded
|
||||
private val episodeDownloadImage: ImageView = itemView.result_episode_download
|
||||
|
||||
private val episodeHolder = itemView.episode_holder
|
||||
|
||||
|
@ -134,11 +144,23 @@ class EpisodeAdapter(
|
|||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
episodeDownload?.visibility = if(hasDownloadSupport) View.VISIBLE else View.GONE
|
||||
|
||||
episodeDownload?.setOnClickListener {
|
||||
if(hasDownloadSupport) {
|
||||
DownloadButtonSetup.setUpButton(
|
||||
null, null, episodeDownloadBar, episodeDownloadImage, null,
|
||||
VideoDownloadHelper.DownloadEpisodeCached(
|
||||
card.name, card.poster, card.episode, card.season, card.id, 0, card.rating, card.descript
|
||||
)
|
||||
) {
|
||||
if(it.action == DOWNLOAD_ACTION_DOWNLOAD) {
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
|
||||
} else {
|
||||
downloadClickCallback.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
episodeDownloadImage.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE
|
||||
episodeDownloadBar.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ import com.lagradost.cloudstream3.UIHelper.requestRW
|
|||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
|
@ -625,9 +627,13 @@ class ResultFragment : Fragment() {
|
|||
EpisodeAdapter(
|
||||
ArrayList(),
|
||||
api.hasDownloadSupport,
|
||||
) { episodeClick ->
|
||||
{ episodeClick ->
|
||||
handleAction(episodeClick)
|
||||
},
|
||||
{ downloadClickEvent ->
|
||||
handleDownloadClick(activity, currentHeaderName, downloadClickEvent)
|
||||
}
|
||||
)
|
||||
|
||||
result_episodes.adapter = adapter
|
||||
result_episodes.layoutManager = GridLayoutManager(context, 1)
|
||||
|
|
|
@ -144,7 +144,7 @@ object VideoDownloadManager {
|
|||
val downloadStatus = HashMap<Int, DownloadType>()
|
||||
val downloadStatusEvent = Event<Pair<Int, DownloadType>>()
|
||||
val downloadEvent = Event<Pair<Int, DownloadActionType>>()
|
||||
val downloadProgressEvent = Event<Pair<Int, Long>>()
|
||||
val downloadProgressEvent = Event<Triple<Int, Long, Long>>()
|
||||
val downloadQueue = LinkedList<DownloadResumePackage>()
|
||||
|
||||
private var hasCreatedNotChanel = false
|
||||
|
@ -542,7 +542,7 @@ object VideoDownloadManager {
|
|||
try {
|
||||
downloadStatus[ep.id] = type
|
||||
downloadStatusEvent.invoke(Pair(ep.id, type))
|
||||
downloadProgressEvent.invoke(Pair(ep.id, bytesDownloaded))
|
||||
downloadProgressEvent.invoke(Triple(ep.id, bytesDownloaded, bytesTotal))
|
||||
} catch (e: Exception) {
|
||||
// IDK MIGHT ERROR
|
||||
}
|
||||
|
@ -626,13 +626,15 @@ object VideoDownloadManager {
|
|||
// RETURN MESSAGE
|
||||
return when {
|
||||
isFailed -> {
|
||||
downloadProgressEvent.invoke(Triple(id, 0, 0))
|
||||
ERROR_CONNECTION_ERROR
|
||||
}
|
||||
isStopped -> {
|
||||
downloadProgressEvent.invoke(Triple(id, 0, 0))
|
||||
deleteFile()
|
||||
}
|
||||
else -> {
|
||||
downloadProgressEvent.invoke(Pair(id, bytesDownloaded))
|
||||
downloadProgressEvent.invoke(Triple(id, bytesDownloaded, bytesTotal))
|
||||
isDone = true
|
||||
updateNotification()
|
||||
SUCCESS_DOWNLOAD_DONE
|
||||
|
@ -715,6 +717,8 @@ object VideoDownloadManager {
|
|||
|
||||
private fun deleteFile(context: Context, id: Int): Boolean {
|
||||
downloadEvent.invoke(Pair(id, DownloadActionType.Stop))
|
||||
downloadProgressEvent.invoke(Triple(id, 0, 0))
|
||||
downloadStatusEvent.invoke(Pair(id, DownloadType.IsStopped))
|
||||
val info = context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return false
|
||||
|
||||
if (isScopedStorage()) {
|
||||
|
|
|
@ -61,16 +61,38 @@
|
|||
android:textColor="@color/textColor" android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
</TextView>
|
||||
|
||||
<FrameLayout
|
||||
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/result_episode_progress_downloaded"
|
||||
android:indeterminate="false"
|
||||
android:progressDrawable="@drawable/circular_progress_bar"
|
||||
android:background="@drawable/circle_shape"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:max="100"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:progress="0"
|
||||
android:visibility="visible"
|
||||
/>
|
||||
<ImageView
|
||||
android:visibility="visible"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="2dp"
|
||||
android:layout_width="30dp"
|
||||
android:id="@+id/episode_download"
|
||||
android:id="@+id/result_episode_download"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:src="@drawable/netflix_download"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/download_descript"/>
|
||||
</FrameLayout>
|
||||
</GridLayout>
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -76,16 +76,40 @@
|
|||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
<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/result_episode_progress_downloaded"
|
||||
android:indeterminate="false"
|
||||
android:progressDrawable="@drawable/circular_progress_bar"
|
||||
android:background="@drawable/circle_shape"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:max="100"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:progress="0"
|
||||
android:visibility="visible"
|
||||
/>
|
||||
<ImageView
|
||||
android:visibility="visible"
|
||||
android:layout_marginStart="-40dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="2dp"
|
||||
android:layout_width="30dp"
|
||||
android:id="@+id/episode_download"
|
||||
android:id="@+id/result_episode_download"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:src="@drawable/netflix_download"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/download_descript"/>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:paddingTop="10dp"
|
||||
|
|
Loading…
Reference in a new issue