moved download view to nicer button

This commit is contained in:
LagradOst 2023-07-15 23:43:09 +02:00
parent 6bc5d86ff9
commit a2a4da5a29
39 changed files with 1295 additions and 882 deletions

View file

@ -1,6 +0,0 @@
package com.lagradost.cloudstream3.ui.download
interface DownloadButtonViewHolder {
var downloadButton : EasyDownloadButton
fun reattachDownloadButton()
}

View file

@ -9,7 +9,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import java.util.Collections
const val DOWNLOAD_ACTION_PLAY_FILE = 0
const val DOWNLOAD_ACTION_DELETE_FILE = 1
@ -31,36 +30,6 @@ class DownloadChildAdapter(
private val clickCallback: (DownloadClickEvent) -> Unit,
) : 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 {
return DownloadChildViewHolder(
DownloadChildEpisodeBinding.inflate(LayoutInflater.from(parent.context), parent, false),
@ -72,7 +41,6 @@ class DownloadChildAdapter(
when (holder) {
is DownloadChildViewHolder -> {
holder.bind(cardList[position])
mBoundViewHolders.add(holder)
}
}
}
@ -85,8 +53,7 @@ class DownloadChildAdapter(
constructor(
val binding: DownloadChildEpisodeBinding,
private val clickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton()
) : RecyclerView.ViewHolder(binding.root) {
/*private val title: TextView = itemView.download_child_episode_text
private val extraInfo: TextView = itemView.download_child_episode_text_extra
@ -95,10 +62,8 @@ class DownloadChildAdapter(
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
private val downloadImage: ImageView = itemView.download_child_episode_download*/
private var localCard: VisualDownloadChildCached? = null
fun bind(card: VisualDownloadChildCached) {
localCard = card
val d = card.data
val posDur = getViewPos(d.id)
@ -113,6 +78,7 @@ class DownloadChildAdapter(
}
}
binding.downloadButton.setDefaultClickListener(card.data,clickCallback)
binding.downloadChildEpisodeText.apply {
text = context.getNameFull(d.name, d.episode, d.season)
@ -120,35 +86,9 @@ class DownloadChildAdapter(
}
downloadButton.setUpButton(
card.currentBytes,
card.totalBytes,
binding.downloadChildEpisodeProgressDownloaded,
binding.downloadChildEpisodeDownload,
binding.downloadChildEpisodeTextExtra,
card.data,
clickCallback
)
binding.downloadChildEpisodeHolder.setOnClickListener {
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
}
}
override fun reattachDownloadButton() {
downloadButton.dispose()
val card = localCard
if (card != null) {
downloadButton.setUpButton(
card.currentBytes,
card.totalBytes,
binding.downloadChildEpisodeProgressDownloaded,
binding.downloadChildEpisodeDownload,
binding.downloadChildEpisodeTextExtra,
card.data,
clickCallback
)
}
}
}
}

View file

@ -30,7 +30,6 @@ class DownloadChildFragment : Fragment() {
}
override fun onDestroyView() {
(binding?.downloadChildList?.adapter as DownloadChildAdapter?)?.killAdapter()
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
binding = null
super.onDestroyView()

View file

@ -70,7 +70,6 @@ class DownloadFragment : Fragment() {
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
downloadDeleteEventListener = null
}
(binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.killAdapter()
binding = null
super.onDestroyView()
}

View file

@ -5,6 +5,7 @@ import android.text.format.Formatter.formatShortFileSize
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.DownloadHeaderEpisodeBinding
@ -22,7 +23,10 @@ data class VisualDownloadHeaderCached(
val child: VideoDownloadHelper.DownloadEpisodeCached?,
)
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
data class DownloadHeaderClickEvent(
val action: Int,
val data: VideoDownloadHelper.DownloadHeaderCached
)
class DownloadHeaderAdapter(
var cardList: List<VisualDownloadHeaderCached>,
@ -30,39 +34,13 @@ class DownloadHeaderAdapter(
private val movieClickCallback: (DownloadClickEvent) -> Unit,
) : 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 {
return DownloadHeaderViewHolder(
DownloadHeaderEpisodeBinding.inflate(LayoutInflater.from(parent.context),parent,false),
DownloadHeaderEpisodeBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
),
clickCallback,
movieClickCallback
)
@ -72,7 +50,6 @@ class DownloadHeaderAdapter(
when (holder) {
is DownloadHeaderViewHolder -> {
holder.bind(cardList[position])
mBoundViewHolders.add(holder)
}
}
}
@ -86,8 +63,7 @@ class DownloadHeaderAdapter(
val binding: DownloadHeaderEpisodeBinding,
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
private val movieClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton()
) : RecyclerView.ViewHolder(binding.root) {
/*private val poster: ImageView? = itemView.download_header_poster
private val title: TextView = itemView.download_header_title
@ -97,11 +73,9 @@ class DownloadHeaderAdapter(
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
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")
fun bind(card: VisualDownloadHeaderCached) {
localCard = card
val d = card.data
binding.downloadHeaderPoster.apply {
@ -113,69 +87,62 @@ class DownloadHeaderAdapter(
binding.apply {
binding.downloadHeaderTitle.text = d.name
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
binding.downloadHeaderTitle.text = d.name
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
//val isMovie = d.type.isMovieType()
if (card.child != null) {
downloadHeaderProgressDownloaded.visibility = View.VISIBLE
//val isMovie = d.type.isMovieType()
if (card.child != null) {
//downloadHeaderProgressDownloaded.visibility = View.VISIBLE
downloadHeaderEpisodeDownload.visibility = View.VISIBLE
binding.downloadHeaderGotoChild.visibility = View.GONE
/*setUpButton(
card.currentBytes,
card.totalBytes,
downloadBar,
downloadImage,
extraInfo,
card.child,
movieClickCallback
)*/
// downloadHeaderEpisodeDownload.visibility = View.VISIBLE
binding.downloadHeaderGotoChild.visibility = View.GONE
episodeHolder.setOnClickListener {
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
}
} else {
downloadHeaderProgressDownloaded.visibility = View.GONE
downloadHeaderEpisodeDownload.visibility = View.GONE
binding.downloadHeaderGotoChild.visibility = View.VISIBLE
downloadButton.setDefaultClickListener(card.child, movieClickCallback)
downloadButton.isVisible = true
/*setUpButton(
card.currentBytes,
card.totalBytes,
downloadBar,
downloadImage,
extraInfo,
card.child,
movieClickCallback
)*/
try {
downloadHeaderInfo.text =
downloadHeaderInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads,
if (card.totalDownloads == 1) downloadHeaderInfo.context.getString(R.string.episode) else downloadHeaderInfo.context.getString(
R.string.episodes
),
mbString
episodeHolder.setOnClickListener {
movieClickCallback.invoke(
DownloadClickEvent(
DOWNLOAD_ACTION_PLAY_FILE,
card.child
)
)
} catch (t : Throwable) {
// you probably formatted incorrectly
downloadHeaderInfo.text = "Error"
logError(t)
}
} else {
downloadButton.isVisible = false
// downloadHeaderProgressDownloaded.visibility = View.GONE
// downloadHeaderEpisodeDownload.visibility = View.GONE
binding.downloadHeaderGotoChild.visibility = View.VISIBLE
try {
downloadHeaderInfo.text =
downloadHeaderInfo.context.getString(R.string.extra_info_format).format(
card.totalDownloads,
if (card.totalDownloads == 1) downloadHeaderInfo.context.getString(R.string.episode) else downloadHeaderInfo.context.getString(
R.string.episodes
),
mbString
)
} catch (t: Throwable) {
// you probably formatted incorrectly
downloadHeaderInfo.text = "Error"
logError(t)
}
episodeHolder.setOnClickListener {
clickCallback.invoke(DownloadHeaderClickEvent(0, d))
}
}
episodeHolder.setOnClickListener {
clickCallback.invoke(DownloadHeaderClickEvent(0, d))
}
}
}
}
override fun reattachDownloadButton() {
downloadButton.dispose()
val card = localCard
if (card?.child != null) {
downloadButton.setUpButton(
card.currentBytes,
card.totalBytes,
binding.downloadHeaderProgressDownloaded,
binding.downloadHeaderEpisodeDownload,
binding.downloadHeaderInfo,
card.child,
movieClickCallback
)
}
}
}

View file

@ -0,0 +1,176 @@
package com.lagradost.cloudstream3.ui.download.button
import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
import androidx.annotation.LayoutRes
import androidx.core.widget.ContentLoadingProgressBar
import com.lagradost.cloudstream3.utils.VideoDownloadManager
typealias DownloadStatusTell = VideoDownloadManager.DownloadType
data class DownloadMetadata(
var id: Int,
var downloadedLength: Long,
var totalLength: Long,
var status: DownloadStatusTell? = null
) {
val progressPercentage : Long get() = if(downloadedLength < 1024) 0 else maxOf(0,minOf (100, (downloadedLength * 100L) / totalLength))
}
abstract class BaseFetchButton(context: Context, attributeSet: AttributeSet) :
FrameLayout(context, attributeSet) {
var persistentId: Int? = null // used to save sessions
lateinit var progressBar: ContentLoadingProgressBar
/*val gid: String? get() = sessionIdToGid[persistentId]
// used for resuming data
var _lastRequestOverride: UriRequest? = null
var lastRequest: UriRequest?
get() = _lastRequestOverride ?: sessionIdToLastRequest[persistentId]
set(value) {
_lastRequestOverride = value
}
var files: List<AbstractClient.JsonFile> = emptyList()*/
protected var isZeroBytes: Boolean = true
fun inflate(@LayoutRes layout: Int) {
inflate(context, layout, this)
}
init {
resetViewData()
}
open fun resetViewData() {
// lastRequest = null
isZeroBytes = true
persistentId = null
}
var currentMetaData: DownloadMetadata =
DownloadMetadata(0, 0, 0, null)
fun setPersistentId(id: Int) {
persistentId = id
currentMetaData.id = id
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, id)?.let { savedData ->
val downloadedBytes = savedData.fileLength
val totalBytes = savedData.totalBytes
/*lastRequest = savedData.uriRequest
files = savedData.files
var totalBytes: Long = 0
var downloadedBytes: Long = 0
for (file in savedData.files) {
downloadedBytes += file.completedLength
totalBytes += file.length
}*/
setProgress(downloadedBytes, totalBytes)
// some extra padding for just in case
val status = VideoDownloadManager.downloadStatus[id]
?: if (downloadedBytes > 1024L && downloadedBytes + 1024L >= totalBytes) DownloadStatusTell.IsDone else DownloadStatusTell.IsPaused
currentMetaData.apply {
this.id = id
this.downloadedLength = downloadedBytes
this.totalLength = totalBytes
this.status = status
}
setStatus(status)
} ?: run {
resetView()
}
}
abstract fun setStatus(status: VideoDownloadManager.DownloadType?)
open fun setProgress(downloadedBytes: Long, totalBytes: Long) {
isZeroBytes = downloadedBytes == 0L
val steps = 10000L
progressBar.max = steps.toInt()
// div by zero error and 1 byte off is ok impo
val progress = (downloadedBytes * steps / (totalBytes + 1L)).toInt()
val animation = ProgressBarAnimation(
progressBar,
progressBar.progress.toFloat(),
progress.toFloat()
).apply {
fillAfter = true
duration =
if (progress > progressBar.progress) // we don't want to animate backward changes in progress
100
else
0L
}
progressBar.startAnimation(animation)
}
fun downloadStatusEvent(data: Pair<Int, VideoDownloadManager.DownloadType>) {
val (id, status) = data
if (id == persistentId) {
currentMetaData.status = status
setStatus(status)
}
}
/*fun downloadDeleteEvent(data: Int) {
}*/
/*fun downloadEvent(data: Pair<Int, VideoDownloadManager.DownloadActionType>) {
val (id, action) = data
}*/
fun downloadProgressEvent(data: Triple<Int, Long, Long>) {
val (id, bytesDownloaded, bytesTotal) = data
if (id == persistentId) {
currentMetaData.downloadedLength = bytesDownloaded
currentMetaData.totalLength = bytesTotal
setProgress(bytesDownloaded, bytesTotal)
}
}
override fun onAttachedToWindow() {
VideoDownloadManager.downloadStatusEvent += ::downloadStatusEvent
//VideoDownloadManager.downloadDeleteEvent += ::downloadDeleteEvent
//VideoDownloadManager.downloadEvent += ::downloadEvent
VideoDownloadManager.downloadProgressEvent += ::downloadProgressEvent
val pid = persistentId
if (pid != null) {
// refresh in case of onDetachedFromWindow -> onAttachedToWindow while still being ???????
setPersistentId(pid)
}
super.onAttachedToWindow()
}
override fun onDetachedFromWindow() {
VideoDownloadManager.downloadStatusEvent -= ::downloadStatusEvent
//VideoDownloadManager.downloadDeleteEvent -= ::downloadDeleteEvent
//VideoDownloadManager.downloadEvent -= ::downloadEvent
VideoDownloadManager.downloadProgressEvent -= ::downloadProgressEvent
super.onDetachedFromWindow()
}
/**
* No checks required. Arg will always include a download with current id
* */
abstract fun updateViewOnDownload(metadata: DownloadMetadata)
/**
* Get a clean slate again, might be useful in recyclerview?
* */
abstract fun resetView()
}

View file

@ -0,0 +1,55 @@
package com.lagradost.cloudstream3.ui.download.button
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.widget.TextView
import androidx.core.view.isVisible
import com.google.android.material.button.MaterialButton
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
class DownloadButton(context: Context, attributeSet: AttributeSet) :
PieFetchButton(context, attributeSet) {
var progressText: TextView? = null
var mainText: TextView? = null
override fun onAttachedToWindow() {
super.onAttachedToWindow()
progressText = findViewById(R.id.result_movie_download_text_precentage)
mainText = findViewById(R.id.result_movie_download_text)
}
override fun setStatus(status: DownloadStatusTell?) {
super.setStatus(status)
val txt = when (status) {
DownloadStatusTell.IsPaused -> R.string.download_paused
DownloadStatusTell.IsDownloading -> R.string.downloading
DownloadStatusTell.IsDone -> R.string.downloaded
else -> R.string.download
}
mainText?.setText(txt)
}
override fun setDefaultClickListener(
card: VideoDownloadHelper.DownloadEpisodeCached,
callback: (DownloadClickEvent) -> Unit
) {
this.setDefaultClickListener(
this.findViewById<MaterialButton>(R.id.download_movie_button),
card,
callback
)
}
@SuppressLint("SetTextI18n")
override fun updateViewOnDownload(metadata: DownloadMetadata) {
super.updateViewOnDownload(metadata)
val isVis = metadata.progressPercentage > 0
progressText?.isVisible = isVis
if (isVis)
progressText?.text = "${metadata.progressPercentage}%"
}
}

View file

@ -0,0 +1,317 @@
package com.lagradost.cloudstream3.ui.download.button
import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.view.animation.AnimationUtils
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DELETE_FILE
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_PAUSE_DOWNLOAD
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_PLAY_FILE
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_RESUME_DOWNLOAD
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import com.lagradost.cloudstream3.utils.VideoDownloadManager
open class PieFetchButton(context: Context, attributeSet: AttributeSet) :
BaseFetchButton(context, attributeSet) {
private var waitingAnimation: Int = 0
private var animateWaiting: Boolean = false
private var activeOutline: Int = 0
private var nonActiveOutline: Int = 0
private var iconInit: Int = 0
private var iconError: Int = 0
private var iconComplete: Int = 0
private var iconActive: Int = 0
private var iconWaiting: Int = 0
private var iconRemoved: Int = 0
private var iconPaused: Int = 0
private var hideWhenIcon: Boolean = true
var overrideLayout: Int? = null
companion object {
val fillArray = arrayOf(
R.drawable.circular_progress_bar_clockwise,
R.drawable.circular_progress_bar_counter_clockwise,
R.drawable.circular_progress_bar_small_to_large,
R.drawable.circular_progress_bar_top_to_bottom,
)
}
private var progressBarBackground: View
private var statusView: ImageView
open fun onInflate() {}
init {
context.obtainStyledAttributes(attributeSet, R.styleable.PieFetchButton, 0, 0).apply {
try {
inflate(
overrideLayout ?: getResourceId(
R.styleable.PieFetchButton_download_layout,
R.layout.download_button_view
)
)
} catch (e: Exception) {
Log.e(
"PieFetchButton", "Error inflating PieFetchButton, " +
"check that you have declared the required aria2c attrs: aria2c_icon_scale aria2c_icon_color aria2c_outline_color aria2c_fill_color"
)
throw e
}
progressBar = findViewById(R.id.progress_downloaded)
progressBarBackground = findViewById(R.id.progress_downloaded_background)
statusView = findViewById(R.id.image_download_status)
animateWaiting = getBoolean(
R.styleable.PieFetchButton_download_animate_waiting,
true
)
hideWhenIcon = getBoolean(
R.styleable.PieFetchButton_download_hide_when_icon,
true
)
waitingAnimation = getResourceId(
R.styleable.PieFetchButton_download_waiting_animation,
R.anim.rotate_around_center_point
)
activeOutline = getResourceId(
R.styleable.PieFetchButton_download_outline_active, R.drawable.circle_shape
)
nonActiveOutline = getResourceId(
R.styleable.PieFetchButton_download_outline_non_active,
R.drawable.circle_shape_dotted
)
iconInit = getResourceId(
R.styleable.PieFetchButton_download_icon_init, R.drawable.netflix_download
)
iconError = getResourceId(
R.styleable.PieFetchButton_download_icon_paused, R.drawable.download_icon_error
)
iconComplete = getResourceId(
R.styleable.PieFetchButton_download_icon_complete, R.drawable.download_icon_done
)
iconPaused = getResourceId(
R.styleable.PieFetchButton_download_icon_paused, 0//R.drawable.download_icon_pause
)
iconActive = getResourceId(
R.styleable.PieFetchButton_download_icon_active, 0 //R.drawable.download_icon_load
)
iconWaiting = getResourceId(
R.styleable.PieFetchButton_download_icon_waiting, 0
)
iconRemoved = getResourceId(
R.styleable.PieFetchButton_download_icon_removed, R.drawable.netflix_download
)
val fillIndex = getInt(R.styleable.PieFetchButton_download_fill, 0)
val progressDrawable = getResourceId(
R.styleable.PieFetchButton_download_fill_override, fillArray[fillIndex]
)
progressBar.progressDrawable = ContextCompat.getDrawable(context, progressDrawable)
recycle()
}
resetView()
onInflate()
}
private var currentStatus: DownloadStatusTell? = null
/*private fun getActivity(): Activity? {
var context = context
while (context is ContextWrapper) {
if (context is Activity) {
return context
}
context = context.baseContext
}
return null
}
fun callback(event : DownloadClickEvent) {
handleDownloadClick(
getActivity(),
event
)
}*/
protected fun setDefaultClickListener(view: View, card: VideoDownloadHelper.DownloadEpisodeCached,
callback: (DownloadClickEvent) -> Unit) {
this.setPersistentId(card.id)
view.setOnClickListener {
if (isZeroBytes) {
callback(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, card))
//callback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data))
} else {
val list = arrayListOf(
Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file),
Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file),
)
currentMetaData.apply {
// DON'T RESUME A DOWNLOADED FILE lastState != VideoDownloadManager.DownloadType.IsDone &&
if ((downloadedLength * 100 / totalLength) < 98) {
list.add(
if (status == 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
) {
callback(DownloadClickEvent(itemId, card))
//callback.invoke(DownloadClickEvent(itemId, data))
}
}
}
view.setOnLongClickListener {
callback(DownloadClickEvent(DOWNLOAD_ACTION_LONG_CLICK, card))
//clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_LONG_CLICK, data))
return@setOnLongClickListener true
}
}
open fun setDefaultClickListener(
card: VideoDownloadHelper.DownloadEpisodeCached,
callback: (DownloadClickEvent) -> Unit
) {
setDefaultClickListener(this,card,callback)
}
/*open fun setDefaultClickListener(requestGetter: suspend BaseFetchButton.() -> List<UriRequest>) {
this.setOnClickListener {
when (this.currentStatus) {
null -> {
setStatus(DownloadStatusTell.IsPending)
ioThread {
val request = requestGetter.invoke(this)
if (request.size == 1) {
performDownload(request.first())
} else if (request.isNotEmpty()) {
performFailQueueDownload(request)
}
}
}
DownloadStatusTell.Paused -> {
resumeDownload()
}
DownloadStatusTell.Active -> {
pauseDownload()
}
DownloadStatusTell.Error -> {
redownload()
}
else -> {}
}
}
}*/
/** Also sets currentStatus */
override fun setStatus(status: DownloadStatusTell?) {
currentStatus = status
//progressBar.isVisible =
// status != null && status != DownloadStatusTell.Complete && status != DownloadStatusTell.Error
//progressBarBackground.isVisible = status != null && status != DownloadStatusTell.Complete
val isPreActive = isZeroBytes && status == DownloadStatusTell.IsDownloading
if (animateWaiting && (status == DownloadStatusTell.IsPending || isPreActive)) {
val animation = AnimationUtils.loadAnimation(context, waitingAnimation)
progressBarBackground.startAnimation(animation)
} else {
progressBarBackground.clearAnimation()
}
val progressDrawable =
if (status == DownloadStatusTell.IsDownloading && !isPreActive) activeOutline else nonActiveOutline
progressBarBackground.background =
ContextCompat.getDrawable(context, progressDrawable)
val drawable = getDrawableFromStatus(status)
statusView.setImageDrawable(drawable)
val isDrawable = drawable != null
statusView.isVisible = isDrawable
val hide = hideWhenIcon && isDrawable
if (hide) {
progressBar.clearAnimation()
progressBarBackground.clearAnimation()
}
progressBarBackground.isGone = hide
progressBar.isGone = hide
}
override fun resetView() {
setStatus(null)
currentMetaData = DownloadMetadata(0, 0, 0, null)
isZeroBytes = true
progressBar.progress = 0
}
override fun updateViewOnDownload(metadata: DownloadMetadata) {
val newStatus = metadata.status
if (newStatus == null) {
resetView()
return
}
val isDone =
newStatus == DownloadStatusTell.IsDone || (metadata.downloadedLength > 1024 && metadata.downloadedLength + 1024 >= metadata.totalLength)
if (isDone)
setStatus(DownloadStatusTell.IsDone)
else {
setProgress(metadata.downloadedLength, metadata.totalLength)
setStatus(newStatus)
}
}
open fun getDrawableFromStatus(status: DownloadStatusTell?): Drawable? {
val drawableInt = when (status) {
DownloadStatusTell.IsPaused -> iconPaused
DownloadStatusTell.IsPending -> iconWaiting
DownloadStatusTell.IsDownloading -> iconActive
DownloadStatusTell.IsFailed -> iconError
DownloadStatusTell.IsDone -> iconComplete
DownloadStatusTell.IsStopped -> iconRemoved
null -> iconInit
}
if (drawableInt == 0) {
return null
}
return ContextCompat.getDrawable(this.context, drawableInt)
}
}

View file

@ -0,0 +1,18 @@
package com.lagradost.cloudstream3.ui.download.button
import android.view.animation.Animation
import android.view.animation.Transformation
import android.widget.ProgressBar
class ProgressBarAnimation(
private val progressBar: ProgressBar,
private val from: Float,
private val to: Float
) :
Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
super.applyTransformation(interpolatedTime, t)
val value = from + (to - from) * interpolatedTime
progressBar.progress = value.toInt()
}
}

View file

@ -13,15 +13,12 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.databinding.ResultEpisodeBinding
import com.lagradost.cloudstream3.databinding.ResultEpisodeLargeBinding
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.UIHelper.setImage
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
import com.lagradost.cloudstream3.utils.VideoDownloadManager
import java.util.*
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
@ -79,49 +76,10 @@ class EpisodeAdapter(
var cardList: MutableList<ResultEpisode> = mutableListOf()
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.itemView.hasFocus()) {
holder.itemView.clearFocus()
}
//(holder.itemView as? FrameLayout?)?.descendantFocusability =
// ViewGroup.FOCUS_BLOCK_DESCENDANTS
if (holder is DownloadButtonViewHolder) {
holder.downloadButton.dispose()
}
}
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
if (holder is DownloadButtonViewHolder) {
holder.downloadButton.dispose()
mBoundViewHolders.remove(holder)
//(holder.itemView as? FrameLayout?)?.descendantFocusability =
// ViewGroup.FOCUS_BLOCK_DESCENDANTS
}
}
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
if (holder is DownloadButtonViewHolder) {
//println("onViewAttachedToWindow = ${holder.absoluteAdapterPosition}")
//holder.itemView.post {
// if (holder.itemView.isAttachedToWindow)
// (holder.itemView as? FrameLayout?)?.descendantFocusability =
// ViewGroup.FOCUS_AFTER_DESCENDANTS
//}
holder.reattachDownloadButton()
}
}
fun updateList(newList: List<ResultEpisode>) {
@ -135,7 +93,7 @@ class EpisodeAdapter(
diffResult.dispatchUpdatesTo(this)
}
fun getItem(position: Int) : ResultEpisode {
private fun getItem(position: Int) : ResultEpisode {
return cardList[position]
}
@ -177,11 +135,9 @@ class EpisodeAdapter(
when (holder) {
is EpisodeCardViewHolderLarge -> {
holder.bind(getItem(position))
mBoundViewHolders.add(holder)
}
is EpisodeCardViewHolderSmall -> {
holder.bind(getItem(position))
mBoundViewHolders.add(holder)
}
}
}
@ -196,11 +152,7 @@ class EpisodeAdapter(
private val hasDownloadSupport: Boolean,
private val clickCallback: (EpisodeClickEvent) -> Unit,
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton()
// TODO TV
) : RecyclerView.ViewHolder(binding.root) {
var localCard: ResultEpisode? = null
@SuppressLint("SetTextI18n")
@ -214,6 +166,24 @@ class EpisodeAdapter(
val isTrueTv = isTrueTvSettings()
binding.apply {
downloadButton.isVisible = hasDownloadSupport
downloadButton.setDefaultClickListener(VideoDownloadHelper.DownloadEpisodeCached(
card.name,
card.poster,
card.episode,
card.season,
card.id,
card.parentId,
card.rating,
card.description,
System.currentTimeMillis(),
)) {
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
} else {
downloadClickCallback.invoke(it)
}
}
val name =
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
@ -280,45 +250,8 @@ class EpisodeAdapter(
return@setOnLongClickListener true
}
binding.resultEpisodeDownload.isVisible = hasDownloadSupport
binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
reattachDownloadButton()
}
override fun reattachDownloadButton() {
downloadButton.dispose()
val card = localCard
if (hasDownloadSupport && card != null) {
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
itemView.context,
card.id
)
downloadButton.setUpButton(
downloadInfo?.fileLength,
downloadInfo?.totalBytes,
binding.resultEpisodeProgressDownloaded,
binding.resultEpisodeDownload,
null,
VideoDownloadHelper.DownloadEpisodeCached(
card.name,
card.poster,
card.episode,
card.season,
card.id,
card.parentId,
card.rating,
card.description,
System.currentTimeMillis(),
)
) {
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
} else {
downloadClickCallback.invoke(it)
}
}
}
//binding.resultEpisodeDownload.isVisible = hasDownloadSupport
//binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
}
}
@ -328,15 +261,9 @@ class EpisodeAdapter(
private val hasDownloadSupport: Boolean,
private val clickCallback: (EpisodeClickEvent) -> Unit,
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
) : RecyclerView.ViewHolder(binding.root), DownloadButtonViewHolder {
override var downloadButton = EasyDownloadButton()
var localCard: ResultEpisode? = null
) : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(card: ResultEpisode) {
localCard = card
val isTrueTv = isTrueTvSettings()
binding.episodeHolder.layoutParams.apply {
@ -344,6 +271,25 @@ class EpisodeAdapter(
}
binding.apply {
downloadButton.isVisible = hasDownloadSupport
downloadButton.setDefaultClickListener(VideoDownloadHelper.DownloadEpisodeCached(
card.name,
card.poster,
card.episode,
card.season,
card.id,
card.parentId,
card.rating,
card.description,
System.currentTimeMillis(),
)) {
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
} else {
downloadClickCallback.invoke(it)
}
}
val name =
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
episodeFiller.isVisible = card.isFiller == true
@ -379,46 +325,8 @@ class EpisodeAdapter(
return@setOnLongClickListener true
}
binding.resultEpisodeDownload.isVisible = hasDownloadSupport
binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
reattachDownloadButton()
}
}
override fun reattachDownloadButton() {
downloadButton.dispose()
val card = localCard
if (hasDownloadSupport && card != null) {
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
itemView.context,
card.id
)
downloadButton.setUpButton(
downloadInfo?.fileLength,
downloadInfo?.totalBytes,
binding.resultEpisodeProgressDownloaded,
binding.resultEpisodeDownload,
null,
VideoDownloadHelper.DownloadEpisodeCached(
card.name,
card.poster,
card.episode,
card.season,
card.id,
card.parentId,
card.rating,
card.description,
System.currentTimeMillis(),
)
) {
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
} else {
downloadClickCallback.invoke(it)
}
}
//binding.resultEpisodeDownload.isVisible = hasDownloadSupport
//binding.resultEpisodeProgressDownloaded.isVisible = hasDownloadSupport
}
}
}

View file

@ -41,7 +41,6 @@ import com.lagradost.cloudstream3.syncproviders.providers.Kitsu
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.download.EasyDownloadButton
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
import com.lagradost.cloudstream3.ui.result.EpisodeAdapter.Companion.getPlayerAction
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
@ -51,7 +50,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
import com.lagradost.cloudstream3.utils.AppUtils.html
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStoreHelper.getVideoWatchState
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
@ -60,14 +58,15 @@ import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import kotlinx.android.synthetic.main.fragment_result.*
import kotlinx.android.synthetic.main.fragment_result.download_button
import kotlinx.android.synthetic.main.fragment_result.result_cast_items
import kotlinx.android.synthetic.main.fragment_result.result_cast_text
import kotlinx.android.synthetic.main.fragment_result.result_coming_soon
import kotlinx.android.synthetic.main.fragment_result.result_data_holder
import kotlinx.android.synthetic.main.fragment_result.result_description
import kotlinx.android.synthetic.main.fragment_result.result_download_movie
import kotlinx.android.synthetic.main.fragment_result.result_dub_select
import kotlinx.android.synthetic.main.fragment_result.result_episode_loading
import kotlinx.android.synthetic.main.fragment_result.result_episode_select
import kotlinx.android.synthetic.main.fragment_result.result_episodes
import kotlinx.android.synthetic.main.fragment_result.result_error_text
import kotlinx.android.synthetic.main.fragment_result.result_finish_loading
@ -79,24 +78,22 @@ import kotlinx.android.synthetic.main.fragment_result.result_meta_rating
import kotlinx.android.synthetic.main.fragment_result.result_meta_site
import kotlinx.android.synthetic.main.fragment_result.result_meta_type
import kotlinx.android.synthetic.main.fragment_result.result_meta_year
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_icon
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text_precentage
import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded
import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded_holder
import kotlinx.android.synthetic.main.fragment_result.result_next_airing
import kotlinx.android.synthetic.main.fragment_result.result_next_airing_time
import kotlinx.android.synthetic.main.fragment_result.result_no_episodes
import kotlinx.android.synthetic.main.fragment_result.result_play_movie
import kotlinx.android.synthetic.main.fragment_result.result_poster
import kotlinx.android.synthetic.main.fragment_result.result_poster_background
import kotlinx.android.synthetic.main.fragment_result.result_poster_holder
import kotlinx.android.synthetic.main.fragment_result.result_reload_connection_open_in_browser
import kotlinx.android.synthetic.main.fragment_result.result_reload_connectionerror
import kotlinx.android.synthetic.main.fragment_result.result_resume_parent
import kotlinx.android.synthetic.main.fragment_result.result_resume_progress_holder
import kotlinx.android.synthetic.main.fragment_result.result_resume_series_button
import kotlinx.android.synthetic.main.fragment_result.result_resume_series_progress
import kotlinx.android.synthetic.main.fragment_result.result_resume_series_progress_text
import kotlinx.android.synthetic.main.fragment_result.result_resume_series_title
import kotlinx.android.synthetic.main.fragment_result.result_season_button
import kotlinx.android.synthetic.main.fragment_result.result_tag
import kotlinx.android.synthetic.main.fragment_result.result_tag_holder
import kotlinx.android.synthetic.main.fragment_result.result_title
@ -278,12 +275,8 @@ open class ResultFragment : ResultTrailerPlayer() {
return inflater.inflate(resultLayout, container, false)
}
private var downloadButton: EasyDownloadButton? = null
override fun onDestroyView() {
updateUIListener = null
(result_episodes?.adapter as? EpisodeAdapter)?.killAdapter()
downloadButton?.dispose()
super.onDestroyView()
}
@ -371,28 +364,9 @@ open class ResultFragment : ResultTrailerPlayer() {
return@setOnLongClickListener true
}
main {
val file =
ioWorkSafe {
context?.let {
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
it,
ep.id
)
}
}
downloadButton?.dispose()
downloadButton = EasyDownloadButton()
downloadButton?.setUpMoreButton(
file?.fileLength,
file?.totalBytes,
result_movie_progress_downloaded ?: return@main,
result_movie_download_icon ?: return@main,
result_movie_download_text ?: return@main,
result_movie_download_text_precentage ?: return@main,
result_download_movie ?: return@main,
true,
val show = viewModel.currentRepo?.api?.hasDownloadSupport == true && !isTvSettings()
if(show) {
download_button?.setDefaultClickListener(
VideoDownloadHelper.DownloadEpisodeCached(
ep.name,
ep.poster,
@ -405,6 +379,7 @@ open class ResultFragment : ResultTrailerPlayer() {
System.currentTimeMillis(),
)
) { click ->
println("Click:$click")
when (click.action) {
DOWNLOAD_ACTION_DOWNLOAD -> {
viewModel.handleAction(
@ -416,13 +391,14 @@ open class ResultFragment : ResultTrailerPlayer() {
else -> handleDownloadClick(activity, click)
}
}
result_movie_progress_downloaded_holder?.isVisible = true
}
download_button?.isVisible = show
}
}
else -> {
result_movie_progress_downloaded_holder?.isVisible = false
download_button?.isVisible = false
result_play_movie?.isVisible = false
}
}

View file

@ -341,7 +341,7 @@ class ResultViewModel2 : ViewModel() {
private var currentIndex: EpisodeIndexer? = null
private var currentRange: EpisodeRange? = null
private var currentShowFillers: Boolean = false
private var currentRepo: APIRepository? = null
var currentRepo: APIRepository? = null
private var currentId: Int? = null
private var fillers: Map<Int, Boolean> = emptyMap()
private var generator: IGenerator? = null

View file

@ -15,6 +15,8 @@ import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.preference.PreferenceManager
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
@ -37,8 +39,10 @@ import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.removeKey
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okhttp3.internal.closeQuietly
@ -88,12 +92,16 @@ object VideoDownloadManager {
@DrawableRes
const val pressToStopIcon = R.drawable.exo_icon_stop
private var updateCount : Int = 0
private val downloadDataUpdateCount = MutableLiveData<Int>()
enum class DownloadType {
IsPaused,
IsDownloading,
IsDone,
IsFailed,
IsStopped,
IsPending
}
enum class DownloadActionType {
@ -271,6 +279,7 @@ object VideoDownloadManager {
DownloadType.IsPaused -> imgPaused
DownloadType.IsFailed -> imgError
DownloadType.IsStopped -> imgStopped
DownloadType.IsPending -> imgDownloading
}
)

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >
<rotate
android:duration="4000"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:repeatMode="restart"
android:toDegrees="360" />
</set>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:innerRadiusRatio="2.5"
android:shape="ring"
android:thickness="0dp"
android:useLevel="false">
<stroke
tools:color="#FFF"
android:width="2dp"
android:color="?attr/download_outline_color"
android:dashWidth="10px"
android:dashGap="10px" />
</shape>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="50"
android:shape="ring"
android:innerRadius="0dp"
android:thicknessRatio="2.65"
android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->
<solid android:color="?attr/download_fill_color" tools:color="#FFF" />
</shape>
</rotate>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:fromDegrees="270"
android:toDegrees="-90">
<shape
android:innerRadiusRatio="50"
android:shape="ring"
android:innerRadius="0dp"
android:thicknessRatio="2.65"
android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->
<solid android:color="?attr/download_fill_color" tools:color="#FFF" />
</shape>
</rotate>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:scaleGravity="center"
android:scaleHeight="100%"
android:scaleWidth="100%">
<shape
android:shape="ring"
android:innerRadius="0dp"
android:thicknessRatio="2.5"
android:useLevel="false"><!-- this line fixes the issue for lollipop api 21 -->
<solid
android:color="?attr/download_fill_color"
tools:color="#FFF" />
</shape>
</scale>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list>
<item>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:scaleGravity="top"
android:scaleHeight="100%"
android:scaleWidth="100%">
<shape
android:shape="rectangle"
android:innerRadius="0dp"
android:thicknessRatio="2.5"
android:useLevel="false"><!-- this line fixes the issue for lollipop api 21 -->
<solid
android:color="?attr/download_fill_color"
tools:color="#FFF" />
</shape>
</scale>
</item>
<item>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:scaleGravity="right"
android:scaleHeight="100%"
android:scaleWidth="100%">
<shape
android:shape="rectangle"
android:innerRadius="0dp"
android:thicknessRatio="2.5"
android:useLevel="false"><!-- this line fixes the issue for lollipop api 21 -->
<solid
android:color="?attr/download_fill_color"
tools:color="#FFF" />
</shape>
</scale>
</item>
</layer-list>

View file

@ -0,0 +1,23 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 17 1.01 L 7 1 C 5.9 1 5 1.9 5 3 L 5 21 C 5 22.1 5.9 23 7 23 L 17 23 C 18.1 23 19 22.1 19 21 L 19 3 C 19 1.9 18.1 1.01 17 1.01 Z M 17 19 L 7 19 L 7 5 L 17 5 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 7.488 13.004 L 9.132 11.36 L 12.492 14.72 L 10.848 16.364 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
<path
android:name="path_2"
android:pathData="M 10.848 16.364 L 9.203 14.72 L 14.894 9.029 L 16.539 10.673 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
</vector>

View file

@ -0,0 +1,23 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 17 1.01 L 7 1 C 5.9 1 5 1.9 5 3 L 5 21 C 5 22.1 5.9 23 7 23 L 17 23 C 18.1 23 19 22.1 19 21 L 19 3 C 19 1.9 18.1 1.01 17 1.01 Z M 17 19 L 7 19 L 7 5 L 17 5 Z M 10.101 13.289 L 10.513 10.311 L 9.848 9.33 L 9.496 8.867 L 11 13 L 9.706 13 L 9.745 15.93 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 15.801 14.763 L 14.157 16.407 L 7.873 10.124 L 9.518 8.479 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
<path
android:name="path_2"
android:pathData="M 14.157 8.479 L 15.801 10.124 L 9.518 16.407 L 7.873 14.763 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19L7,19L7,5h10v14zM16,13h-3L13,8h-2v5L8,13l4,4 4,-4z" />
</vector>

View file

@ -0,0 +1,18 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 17 1.01 L 7 1 C 5.9 1 5 1.9 5 3 L 5 21 C 5 22.1 5.9 23 7 23 L 17 23 C 18.1 23 19 22.1 19 21 L 19 3 C 19 1.9 18.1 1.01 17 1.01 Z M 17 19 L 7 19 L 7 5 L 17 5 Z M 10.101 13.289 L 10.513 10.311 L 9.848 9.33 L 9.496 8.867 L 11 13 L 9.706 13 L 9.745 15.93 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 9.104 8.931 L 11.129 8.931 L 11.129 15.956 L 9.104 15.956 Z M 12.871 8.931 L 14.896 8.931 L 14.896 15.956 L 12.871 15.956 Z"
android:fillColor="@android:color/white"
android:strokeWidth="1"/>
</vector>

View file

@ -1,105 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:nextFocusLeft="@id/episode_poster"
android:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder"
app:cardElevation="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="@color/transparent"
android:id="@+id/episode_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:foreground="@drawable/outline_drawable"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardElevation="0dp">
android:foreground="@drawable/outline_drawable"
android:layout_margin="5dp">
<LinearLayout
android:padding="5dp"
android:layout_width="100dp"
android:orientation="vertical"
android:layout_height="wrap_content">
android:layout_width="100dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
<FrameLayout
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<androidx.cardview.widget.CardView
app:cardCornerRadius="35dp"
android:layout_width="70dp"
android:layout_height="70dp"
android:foreground="@drawable/outline_drawable">
android:layout_width="70dp"
android:layout_height="70dp"
android:foreground="@drawable/outline_drawable"
app:cardCornerRadius="35dp">
<ImageView
android:nextFocusLeft="@id/result_episode_download"
android:nextFocusRight="@id/episode_holder"
android:id="@+id/actor_image"
tools:src="@drawable/example_poster"
android:id="@+id/actor_image"
android:layout_width="match_parent"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des" />
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des"
android:scaleType="centerCrop"
tools:src="@drawable/example_poster" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:id="@+id/voice_actor_image_holder"
android:layout_gravity="end|bottom"
app:cardCornerRadius="20dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:foreground="@drawable/outline_drawable">
android:id="@+id/voice_actor_image_holder"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="end|bottom"
android:foreground="@drawable/outline_drawable"
app:cardCornerRadius="20dp">
<ImageView
android:nextFocusLeft="@id/result_episode_download"
android:nextFocusRight="@id/episode_holder"
android:id="@+id/voice_actor_image"
android:layout_width="match_parent"
android:id="@+id/voice_actor_image"
tools:src="@drawable/example_poster"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des" />
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des"
android:scaleType="centerCrop"
tools:src="@drawable/example_poster" />
</androidx.cardview.widget.CardView>
</FrameLayout>
<LinearLayout
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingTop="3dp"
android:paddingBottom="3dp">
<TextView
android:id="@+id/actor_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:textColor="?attr/textColor"
android:textStyle="bold"
tools:text="Ackerman, Mikasa" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/actor_name"
tools:text="Ackerman, Mikasa"
android:textStyle="bold"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/voice_actor_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="?attr/grayTextColor"
tools:text="voiceactor" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/voice_actor_name"
tools:text="voiceactor"
android:textColor="?attr/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/actor_extra"
tools:text="Main"
android:textColor="?attr/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/actor_extra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="?attr/grayTextColor"
tools:text="Main" />
</LinearLayout>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<com.lagradost.cloudstream3.ui.download.button.DownloadButton
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/result_download_movie"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
app:download_layout="@layout/download_button_layout" />

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/download_movie_button"
style="@style/BlackButton"
android:layout_width="match_parent"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:visibility="visible" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<include
layout="@layout/download_button_view"
android:layout_width="30dp"
android:layout_height="30dp" />
<TextView
android:id="@+id/result_movie_download_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:gravity="center"
android:letterSpacing="0.09"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
tools:text="Downloading" />
<TextView
android:id="@+id/result_movie_download_text_precentage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:letterSpacing="0.09"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="68%"
tools:visibility="visible" />
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:background="@android:color/holo_blue_light">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/progress_downloaded"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:indeterminate="false"
android:max="100"
android:progress="0"
tools:progress="60"
android:progressDrawable="@drawable/circular_progress_bar_top_to_bottom"
android:visibility="visible" />
<View
android:id="@+id/progress_downloaded_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/circle_shape_dotted" />
<ImageView
android:scaleX="?attr/download_icon_scale"
android:scaleY="?attr/download_icon_scale"
tools:visibility="visible"
android:id="@+id/image_download_status"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="visible"
app:tint="?attr/download_icon_color" />
</FrameLayout>

View file

@ -1,118 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:nextFocusRight="@id/download_child_episode_download"
android:nextFocusLeft="@id/nav_rail_view"
android:id="@+id/download_child_episode_holder"
android:layout_width="match_parent"
android:id="@+id/download_child_episode_holder"
android:layout_width="match_parent"
android:layout_height="50dp"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp"
android:foreground="@drawable/outline_drawable"
android:layout_marginBottom="5dp">
android:layout_height="50dp"
android:layout_marginBottom="5dp"
android:foreground="@drawable/outline_drawable"
android:nextFocusLeft="@id/nav_rail_view"
android:nextFocusRight="@id/download_button"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardElevation="0dp">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/download_child_episode_progress"
android:id="@+id/download_child_episode_progress"
android:layout_marginBottom="-1.5dp"
android:progressTint="?attr/colorPrimary"
android:progressBackgroundTint="?attr/colorPrimary"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
tools:progress="50"
android:layout_gravity="bottom"
android:layout_height="5dp" />
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_gravity="bottom"
android:layout_marginBottom="-1.5dp"
android:progressBackgroundTint="?attr/colorPrimary"
android:progressTint="?attr/colorPrimary"
tools:progress="50" />
<GridLayout
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:attr/selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/download_child_episode_play"
android:visibility="gone"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_baseline_play_arrow_24"
android:contentDescription="@string/episode_play_img_des" />
android:id="@+id/download_child_episode_play"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:contentDescription="@string/episode_play_img_des"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="50dp"
android:orientation="vertical">
<TextView
android:id="@+id/download_child_episode_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginEnd="50dp"
android:layout_width="match_parent">
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="?attr/textColor"
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1" />
<TextView
android:id="@+id/download_child_episode_text"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:singleLine="true"
android:textColor="?attr/textColor"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/download_child_episode_text_extra"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
tools:text="128MB / 237MB"
android:textColor="?attr/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
android:id="@+id/download_child_episode_text_extra"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:gravity="center_vertical"
android:textColor="?attr/grayTextColor"
tools:text="128MB / 237MB" />
</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:id="@+id/download_child_episode_progress_downloaded"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_width="40dp"
android:layout_height="40dp"
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:nextFocusRight="@id/download_child_episode_holder"
android:nextFocusLeft="@id/download_child_episode_holder"
android:id="@+id/download_child_episode_download"
android:visibility="visible"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="10dp"
android:layout_width="50dp"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_play_arrow_24"
app:tint="?attr/textColor"
android:contentDescription="@string/download" />
</FrameLayout>
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
android:id="@+id/download_button"
android:layout_width="@dimen/download_size"
android:layout_height="@dimen/download_size"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="-50dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="10dp" />
</GridLayout>
</androidx.cardview.widget.CardView>

View file

@ -1,103 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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"
android:layout_width="match_parent"
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_marginEnd="10dp"
android:layout_marginTop="10dp">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/episode_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:foreground="@drawable/outline_drawable"
app:cardBackgroundColor="?attr/boxItemBackground"
app:cardCornerRadius="@dimen/rounded_image_radius">
<LinearLayout
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:orientation="horizontal">
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
<androidx.cardview.widget.CardView
android:layout_width="70dp"
android:layout_height="104dp">
android:layout_width="70dp"
android:layout_height="104dp">
<ImageView
android:id="@+id/download_header_poster"
tools:src="@drawable/example_poster"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des" />
android:id="@+id/download_header_poster"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/episode_poster_img_des"
android:scaleType="centerCrop"
tools:src="@drawable/example_poster" />
</androidx.cardview.widget.CardView>
<LinearLayout
android:layout_marginStart="15dp"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_marginEnd="70dp"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="15dp"
android:layout_marginEnd="70dp"
android:orientation="vertical">
<TextView
android:id="@+id/download_header_title"
tools:text="Perfect Run"
android:textStyle="bold"
android:textColor="?attr/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/download_header_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/textColor"
android:textStyle="bold"
tools:text="Perfect Run" />
<TextView
android:id="@+id/download_header_info"
tools:text="1 episode | 285MB"
android:textColor="?attr/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/download_header_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?attr/grayTextColor"
tools:text="1 episode | 285MB" />
</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" />
android:id="@+id/download_header_goto_child"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="-50dp"
android:contentDescription="@string/download"
android:padding="50dp"
android:src="@drawable/ic_baseline_keyboard_arrow_right_24" />
<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"
android:background="@drawable/circle_shape"
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:padding="10dp"
android:layout_width="50dp"
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>
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
android:id="@+id/download_button"
android:layout_width="@dimen/download_size"
android:layout_height="@dimen/download_size"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="-50dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="10dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View file

@ -601,89 +601,11 @@
android:focusable="true"
android:layout_width="match_parent" />-->
<FrameLayout
android:id="@+id/result_movie_progress_downloaded_holder"
<com.lagradost.cloudstream3.ui.download.button.DownloadButton
android:id="@+id/download_button"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/result_download_movie"
style="@style/BlackButton"
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:clickable="true"
android:focusable="true"
android:nextFocusUp="@id/result_play_movie"
android:nextFocusDown="@id/result_season_button"
android:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/result_movie_progress_downloaded"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="end|center_vertical"
android:layout_margin="5dp"
android:background="@drawable/circle_shape"
android:indeterminate="false"
android:max="100"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:progress="30"
android:progressDrawable="@drawable/circular_progress_bar_filled"
android:visibility="visible" />
<ImageView
android:id="@+id/result_movie_download_icon"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/download"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="visible"
app:tint="?attr/white" />
<TextView
android:id="@+id/result_movie_download_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:letterSpacing="0.09"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
tools:text="Downloading" />
<TextView
android:id="@+id/result_movie_download_text_precentage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:letterSpacing="0.09"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="68%" />
</LinearLayout>
</FrameLayout>
android:layout_height="wrap_content"
app:download_layout="@layout/download_button_layout" />
<!--<androidx.core.widget.ContentLoadingProgressBar
android:layout_width="match_parent"

View file

@ -455,6 +455,7 @@
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusRight="@id/download_button"
android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_resume_series_button_play"
android:text="@string/play_trailer_button"
@ -463,95 +464,14 @@
</com.google.android.material.button.MaterialButton>
<FrameLayout
android:id="@+id/result_movie_progress_downloaded_holder"
<com.lagradost.cloudstream3.ui.download.button.DownloadButton
android:id="@+id/download_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusRight="@id/result_bookmark_button">
app:download_layout="@layout/download_button_layout" />
<com.google.android.material.button.MaterialButton
android:id="@+id/result_download_movie"
style="@style/BlackButton"
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:clickable="true"
android:focusable="true"
android:nextFocusLeft="@id/result_play_trailer"
android:nextFocusUp="@id/result_cast_items"
android:nextFocusDown="@id/result_resume_series_button_play"
android:visibility="visible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/result_movie_progress_downloaded"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="end|center_vertical"
android:layout_margin="5dp"
android:background="@drawable/circle_shape"
android:indeterminate="false"
android:max="100"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:progress="30"
android:progressDrawable="@drawable/circular_progress_bar_filled"
android:visibility="visible" />
<ImageView
android:id="@+id/result_movie_download_icon"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/download"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="visible"
app:tint="?attr/white" />
<TextView
android:id="@+id/result_movie_download_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:letterSpacing="0.09"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
tools:text="Downloading" />
<TextView
android:id="@+id/result_movie_download_text_precentage"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:letterSpacing="0.09"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textAllCaps="false"
android:textColor="?attr/textColor"
android:textSize="15sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="68%" />
</LinearLayout>
</FrameLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/result_bookmark_button"
@ -563,7 +483,7 @@
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:minWidth="250dp"
android:nextFocusLeft="@id/result_movie_progress_downloaded_holder"
android:nextFocusLeft="@id/download_button"
android:nextFocusRight="@id/result_bookmark_button"
android:nextFocusDown="@id/result_resume_series_button_play"
android:text="@string/type_none"

View file

@ -40,7 +40,6 @@
android:foreground="@drawable/outline_drawable">
<ImageView
android:nextFocusLeft="@id/result_episode_download"
android:nextFocusRight="@id/episode_holder"
android:id="@+id/episode_poster"

View file

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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"
android:nextFocusRight="@id/result_episode_download"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/episode_holder"
android:id="@+id/episode_holder"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="5dp"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp"
android:layout_marginBottom="5dp">
android:nextFocusRight="@id/download_button"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="@dimen/rounded_image_radius"
app:cardElevation="0dp">
<!--
android:nextFocusLeft="@id/result_episode_download"
-->
@ -39,91 +39,63 @@
</View>
</LinearLayout>-->
<androidx.core.widget.ContentLoadingProgressBar
android:layout_marginBottom="-1.5dp"
android:id="@+id/episode_progress"
android:progressTint="?attr/colorPrimary"
android:progressBackgroundTint="?attr/colorPrimary"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
tools:progress="50"
android:layout_gravity="bottom"
android:layout_height="5dp" />
android:id="@+id/episode_progress"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_gravity="bottom"
android:layout_marginBottom="-1.5dp"
android:progressBackgroundTint="?attr/colorPrimary"
android:progressTint="?attr/colorPrimary"
tools:progress="50" />
<LinearLayout
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:attr/selectableItemBackgroundBorderless">
<ImageView
app:tint="?attr/textColor"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_gravity="center_vertical"
android:id="@+id/episode_play"
android:src="@drawable/ic_baseline_play_arrow_24"
android:contentDescription="@string/episode_play_img_des"
android:layout_height="match_parent"
android:layout_width="wrap_content" />
android:id="@+id/episode_play"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:contentDescription="@string/episode_play_img_des"
android:src="@drawable/ic_baseline_play_arrow_24"
app:tint="?attr/textColor" />
<!--marquee_forever-->
<com.google.android.material.button.MaterialButton
android:layout_gravity="center"
style="@style/SmallBlackButton"
android:text="@string/filler"
android:id="@+id/episode_filler" />
android:id="@+id/episode_filler"
style="@style/SmallBlackButton"
android:layout_gravity="center"
android:text="@string/filler" />
<TextView
android:id="@+id/episode_text"
android:layout_marginStart="10dp"
android:layout_marginEnd="50dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
tools:text="Episode 1"
android:textColor="?attr/textColor"
android:id="@+id/episode_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_marginEnd="50dp"
android:ellipsize="marquee"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:gravity="center_vertical"
android:marqueeRepeatLimit="0"
android:marqueeRepeatLimit="0"
android:singleLine="true"
android:scrollHorizontally="true"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:textColor="?attr/textColor"
tools:text="Episode 1" />
</LinearLayout>
<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" />
<!--
android:nextFocusRight="@id/episode_holder"-->
<ImageView
android:nextFocusLeft="@id/episode_holder"
app:tint="?attr/white"
android:id="@+id/result_episode_download"
android:visibility="visible"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:padding="10dp"
android:layout_width="50dp"
android:background="?selectableItemBackgroundBorderless"
android:src="@drawable/ic_baseline_play_arrow_24"
android:contentDescription="@string/download" />
</FrameLayout>
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
android:id="@+id/download_button"
android:layout_width="@dimen/download_size"
android:layout_height="@dimen/download_size"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="-50dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="10dp" />
</androidx.cardview.widget.CardView>

View file

@ -8,7 +8,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:nextFocusRight="@id/result_episode_download"
android:nextFocusRight="@id/download_button"
app:cardBackgroundColor="?attr/boxItemBackground"
app:cardCornerRadius="@dimen/rounded_image_radius">
@ -39,7 +39,7 @@
android:contentDescription="@string/episode_poster_img_des"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:nextFocusRight="@id/result_episode_download"
android:nextFocusRight="@id/download_button"
android:scaleType="centerCrop"
tools:src="@drawable/example_poster" />
@ -100,42 +100,14 @@
tools:text="Rated: 8.8" />
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginStart="-50dp">
<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/result_episode_progress_downloaded"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="end|center_vertical"
android:layout_margin="5dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="@drawable/circle_shape"
android:indeterminate="false"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/circular_progress_bar"
android:visibility="visible" />
<ImageView
android:id="@+id/result_episode_download"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/download"
android:nextFocusLeft="@id/episode_poster"
android:padding="10dp"
android:src="@drawable/ic_baseline_play_arrow_24"
android:visibility="visible"
app:tint="?attr/white" />
</FrameLayout>
<com.lagradost.cloudstream3.ui.download.button.PieFetchButton
android:id="@+id/download_button"
android:layout_width="@dimen/download_size"
android:layout_height="@dimen/download_size"
android:layout_gravity="center_vertical|end"
android:layout_marginStart="-50dp"
android:background="?selectableItemBackgroundBorderless"
android:padding="10dp" />
</LinearLayout>
<TextView

View file

@ -3,7 +3,6 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder_large"
android:layout_width="wrap_content"

View file

@ -2,7 +2,6 @@
<androidx.cardview.widget.CardView 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"
android:nextFocusRight="@id/result_episode_download"
android:id="@+id/episode_holder"
android:layout_width="wrap_content"

View file

@ -17,6 +17,39 @@
<attr name="header_text" format="string" />
</declare-styleable>
<declare-styleable name="PieFetchButton">
<attr name="download_layout" format="reference" />
<attr name="download_background_progress" format="reference" />
<attr name="download_outline_active" format="reference" />
<attr name="download_outline_non_active" format="reference" />
<attr name="download_waiting_animation" format="reference" />
<attr name="download_progress_drawable" format="reference" />
<attr name="download_animate_waiting" format="boolean" />
<attr name="download_fill_color" format="color" />
<attr name="download_outline_color" format="color" />
<attr name="download_icon_color" format="color" />
<attr name="download_icon_scale" format="float" />
<attr name="download_fill" format="enum">
<enum name="clockwise" value="0" />
<enum name="counter_clockwise" value="1" />
<enum name="small_to_large" value="2" />
<!--<enum name="top_to_bottom" value="3" />-->
</attr>
<attr name="download_fill_override" format="reference" />
<attr name="download_hide_when_icon" format="boolean" />
<attr name="download_icon_init" format="reference" />
<attr name="download_icon_error" format="reference" />
<attr name="download_icon_complete" format="reference" />
<attr name="download_icon_active" format="reference" />
<attr name="download_icon_waiting" format="reference" />
<attr name="download_icon_removed" format="reference" />
<attr name="download_icon_paused" format="reference" />
</declare-styleable>
<declare-styleable name="MainColors">
<attr name="colorPrimary" format="color" />
<attr name="colorSearch" format="color" />

View file

@ -17,4 +17,7 @@
<dimen name="storage_radius">3dp</dimen>
<dimen name="navbar_width">62dp</dimen>
<dimen name="download_size">50dp</dimen>
</resources>

View file

@ -65,6 +65,12 @@
<item name="white">#FFF</item>
<item name="preferenceTheme">@style/CustomPreferenceThemeOverlay</item>
<item name="download_icon_color">?attr/white</item>
<item name="download_fill_color">?attr/white</item>
<item name="download_outline_color">?attr/white</item>
<item name="download_icon_scale">1.0</item>
</style>
<style name="ListViewStyle" parent="Widget.AppCompat.ListView">