forked from recloudstream/cloudstream
download movie stuff
This commit is contained in:
parent
423ee144fd
commit
77778bdbb6
16 changed files with 176 additions and 149 deletions
|
@ -205,6 +205,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
// this.startService(mServiceIntent)
|
// this.startService(mServiceIntent)
|
||||||
//}
|
//}
|
||||||
//settingsManager.getBoolean("disable_automatic_data_downloads", true) &&
|
//settingsManager.getBoolean("disable_automatic_data_downloads", true) &&
|
||||||
|
|
||||||
|
// TODO RETURN TO TRUE
|
||||||
|
/*
|
||||||
if (isUsingMobileData()) {
|
if (isUsingMobileData()) {
|
||||||
Toast.makeText(this, "Downloads not resumed on mobile data", Toast.LENGTH_LONG).show()
|
Toast.makeText(this, "Downloads not resumed on mobile data", Toast.LENGTH_LONG).show()
|
||||||
} else {
|
} else {
|
||||||
|
@ -226,7 +229,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
resumeQueue?.sortedBy { it.index }?.forEach {
|
resumeQueue?.sortedBy { it.index }?.forEach {
|
||||||
VideoDownloadManager.downloadFromResume(this, it.pkg)
|
VideoDownloadManager.downloadFromResume(this, it.pkg)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
val castContext = CastContext.getSharedInstance(applicationContext)
|
val castContext = CastContext.getSharedInstance(applicationContext)
|
||||||
fun buildMediaQueueItem(video: String): MediaQueueItem {
|
fun buildMediaQueueItem(video: String): MediaQueueItem {
|
||||||
|
|
|
@ -214,7 +214,7 @@ class DubbedAnimeProvider : MainAPI() {
|
||||||
|
|
||||||
val img = fixUrl(document.select("div.fkimgs > img").attr("src"))
|
val img = fixUrl(document.select("div.fkimgs > img").attr("src"))
|
||||||
return AnimeLoadResponse(
|
return AnimeLoadResponse(
|
||||||
null, null, title, slug, this.name, TvType.Anime, img, year, ArrayList(episodes), null, null, descript,
|
null, null, title, "$mainUrl/$slug", this.name, TvType.Anime, img, year, ArrayList(episodes), null, null, descript,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ object DownloadButtonSetup {
|
||||||
info.path.toString(),
|
info.path.toString(),
|
||||||
click.data.id,
|
click.data.id,
|
||||||
headerName ?: "null",
|
headerName ?: "null",
|
||||||
click.data.episode,
|
if (click.data.episode <= 0) null else click.data.episode,
|
||||||
click.data.season
|
click.data.season
|
||||||
),
|
),
|
||||||
act.getViewPos(click.data.id)?.position ?: 0
|
act.getViewPos(click.data.id)?.position ?: 0
|
||||||
|
@ -194,8 +194,8 @@ object DownloadButtonSetup {
|
||||||
Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file),
|
Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file),
|
||||||
)
|
)
|
||||||
|
|
||||||
// DON'T RESUME A DOWNLOADED FILE
|
// DON'T RESUME A DOWNLOADED FILE lastState != VideoDownloadManager.DownloadType.IsDone &&
|
||||||
if (lastState != VideoDownloadManager.DownloadType.IsDone && ((currentBytes * 100 / totalBytes) < 98)) {
|
if ((currentBytes * 100 / totalBytes) < 98) {
|
||||||
list.add(
|
list.add(
|
||||||
if (lastState == VideoDownloadManager.DownloadType.IsDownloading)
|
if (lastState == VideoDownloadManager.DownloadType.IsDownloading)
|
||||||
Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download)
|
Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download)
|
||||||
|
|
|
@ -99,94 +99,10 @@ class DownloadChildAdapter(
|
||||||
card.data,
|
card.data,
|
||||||
clickCallback
|
clickCallback
|
||||||
)
|
)
|
||||||
/*
|
|
||||||
val totalMbString = "%.1f".format(card.totalBytes / 1000000f)
|
|
||||||
|
|
||||||
var lastState: VideoDownloadManager.DownloadType? = null
|
|
||||||
var currentBytes: Long = card.currentBytes
|
|
||||||
|
|
||||||
fun changeDownloadImage(state: VideoDownloadManager.DownloadType) {
|
|
||||||
runOnMainThread {
|
|
||||||
val img = 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
|
|
||||||
}
|
|
||||||
downloadImage?.setImageResource(img)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fixDownloadedBytes(setCurrentBytes: Long, animate : Boolean) {
|
|
||||||
currentBytes = setCurrentBytes
|
|
||||||
runOnMainThread {
|
|
||||||
val currentMbString = "%.1f".format(currentBytes / 1000000f)
|
|
||||||
|
|
||||||
extraInfo?.text =
|
|
||||||
"${currentMbString}MB / ${totalMbString}MB"
|
|
||||||
|
|
||||||
progressBarDownload?.let { bar ->
|
|
||||||
bar.max = (card.totalBytes / 1000).toInt()
|
|
||||||
|
|
||||||
if(animate) {
|
|
||||||
val animation: ObjectAnimator = ObjectAnimator.ofInt(
|
|
||||||
bar,
|
|
||||||
"progress",
|
|
||||||
bar.progress,
|
|
||||||
(currentBytes / 1000).toInt()
|
|
||||||
)
|
|
||||||
animation.duration = 500
|
|
||||||
animation.setAutoCancel(true)
|
|
||||||
animation.interpolator = DecelerateInterpolator()
|
|
||||||
animation.start()
|
|
||||||
} else {
|
|
||||||
bar.progress = (currentBytes / 1000).toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fixDownloadedBytes(card.currentBytes, false)
|
|
||||||
changeDownloadImage(getDownloadState(card.data.id))
|
|
||||||
|
|
||||||
VideoDownloadManager.downloadProgressEvent += { downloadData ->
|
|
||||||
if (card.data.id == downloadData.first) {
|
|
||||||
fixDownloadedBytes(downloadData.second, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoDownloadManager.downloadStatusEvent += { downloadData ->
|
|
||||||
if (card.data.id == downloadData.first) {
|
|
||||||
if (lastState != downloadData.second) { // TO PREVENT WASTING UI TIME
|
|
||||||
lastState = downloadData.second
|
|
||||||
changeDownloadImage(downloadData.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadImage.setOnClickListener {
|
|
||||||
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 / card.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, d))
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,18 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.content.ContentProviderCompat.requireContext
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
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
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||||
|
@ -88,12 +80,17 @@ class DownloadChildFragment : Fragment() {
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
) { click ->
|
) { click ->
|
||||||
handleDownloadClick(activity, name, click)
|
handleDownloadClick(activity, name, click)
|
||||||
when (click.action) {
|
}
|
||||||
DOWNLOAD_ACTION_DELETE_FILE -> {
|
|
||||||
|
VideoDownloadManager.downloadDeleteEvent += { id ->
|
||||||
|
val list = (download_child_list?.adapter as DownloadChildAdapter?)?.cardList
|
||||||
|
if (list != null) {
|
||||||
|
if (list.any { it.data.id == id }) {
|
||||||
updateList(folder)
|
updateList(folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
download_child_list.adapter = adapter
|
download_child_list.adapter = adapter
|
||||||
download_child_list.layoutManager = GridLayoutManager(context, 1)
|
download_child_list.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,16 @@ import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.isMovieType
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
import com.lagradost.cloudstream3.mvvm.observe
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
|
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
|
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||||
import kotlinx.android.synthetic.main.fragment_downloads.*
|
import kotlinx.android.synthetic.main.fragment_downloads.*
|
||||||
import kotlinx.android.synthetic.main.fragment_result.*
|
import kotlinx.android.synthetic.main.fragment_result.*
|
||||||
|
|
||||||
|
|
||||||
class DownloadFragment : Fragment() {
|
class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
private lateinit var downloadsViewModel: DownloadViewModel
|
private lateinit var downloadsViewModel: DownloadViewModel
|
||||||
|
|
||||||
private fun getBytesAsText(bytes: Long): String {
|
private fun getBytesAsText(bytes: Long): String {
|
||||||
|
@ -40,6 +41,11 @@ class DownloadFragment : Fragment() {
|
||||||
this.layoutParams = param
|
this.layoutParams = param
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setList(list : List<VisualDownloadHeaderCached>) {
|
||||||
|
(download_list?.adapter as DownloadHeaderAdapter? ?: return).cardList = list
|
||||||
|
(download_list?.adapter as DownloadHeaderAdapter? ?: return).notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -52,8 +58,7 @@ class DownloadFragment : Fragment() {
|
||||||
text_no_downloads.text = it
|
text_no_downloads.text = it
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.headerCards) {
|
observe(downloadsViewModel.headerCards) {
|
||||||
(download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).cardList = it
|
setList(it)
|
||||||
(download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
observe(downloadsViewModel.availableBytes) {
|
observe(downloadsViewModel.availableBytes) {
|
||||||
download_free_txt?.text = "Free • ${getBytesAsText(it)}GB"
|
download_free_txt?.text = "Free • ${getBytesAsText(it)}GB"
|
||||||
|
@ -76,11 +81,10 @@ class DownloadFragment : Fragment() {
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
DownloadHeaderAdapter(
|
DownloadHeaderAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
) { click ->
|
{ click ->
|
||||||
if (click.data.type.isMovieType()) {
|
if (click.data.type.isMovieType()) {
|
||||||
//TODO MOVIE
|
//wont be called
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
|
val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString())
|
||||||
val navController = activity?.findNavController(R.id.nav_host_fragment)
|
val navController = activity?.findNavController(R.id.nav_host_fragment)
|
||||||
navController?.navigate(R.id.navigation_download_child, Bundle().apply {
|
navController?.navigate(R.id.navigation_download_child, Bundle().apply {
|
||||||
|
@ -88,7 +92,25 @@ class DownloadFragment : Fragment() {
|
||||||
putString("name", click.data.name)
|
putString("name", click.data.name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{ downloadClickEvent ->
|
||||||
|
handleDownloadClick(activity, downloadClickEvent.data.name, downloadClickEvent)
|
||||||
|
if(downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||||
|
downloadsViewModel.updateList(requireContext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
VideoDownloadManager.downloadDeleteEvent += { id ->
|
||||||
|
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
||||||
|
if (list != null) {
|
||||||
|
if (list.any { it.data.id == id }) {
|
||||||
|
setList(ArrayList())
|
||||||
|
downloadsViewModel.updateList(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
download_list.adapter = adapter
|
download_list.adapter = adapter
|
||||||
download_list.layoutManager = GridLayoutManager(context, 1)
|
download_list.layoutManager = GridLayoutManager(context, 1)
|
||||||
downloadsViewModel.updateList(requireContext())
|
downloadsViewModel.updateList(requireContext())
|
||||||
|
|
|
@ -7,11 +7,13 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.isMovieType
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.setUpButton
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
||||||
|
|
||||||
|
@ -19,7 +21,9 @@ data class VisualDownloadHeaderCached(
|
||||||
val currentOngoingDownloads: Int,
|
val currentOngoingDownloads: Int,
|
||||||
val totalDownloads: Int,
|
val totalDownloads: Int,
|
||||||
val totalBytes: Long,
|
val totalBytes: Long,
|
||||||
|
val currentBytes: Long,
|
||||||
val data: VideoDownloadHelper.DownloadHeaderCached,
|
val data: VideoDownloadHelper.DownloadHeaderCached,
|
||||||
|
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
||||||
|
@ -27,13 +31,15 @@ data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelp
|
||||||
class DownloadHeaderAdapter(
|
class DownloadHeaderAdapter(
|
||||||
var cardList: List<VisualDownloadHeaderCached>,
|
var cardList: List<VisualDownloadHeaderCached>,
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return DownloadHeaderViewHolder(
|
return DownloadHeaderViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(R.layout.download_header_episode, parent, false),
|
LayoutInflater.from(parent.context).inflate(R.layout.download_header_episode, parent, false),
|
||||||
clickCallback
|
clickCallback,
|
||||||
|
movieClickCallback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,12 +59,17 @@ class DownloadHeaderAdapter(
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView) {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
private val poster: ImageView = itemView.download_header_poster
|
private val poster: ImageView = itemView.download_header_poster
|
||||||
private val title: TextView = itemView.download_header_title
|
private val title: TextView = itemView.download_header_title
|
||||||
private val extraInfo: TextView = itemView.download_header_info
|
private val extraInfo: TextView = itemView.download_header_info
|
||||||
private val holder: CardView = itemView.episode_holder
|
private val holder: CardView = itemView.episode_holder
|
||||||
|
|
||||||
|
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
|
||||||
|
private val downloadImage: ImageView = itemView.download_header_episode_download
|
||||||
|
private val normalImage: ImageView = itemView.download_header_goto_child
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: VisualDownloadHeaderCached) {
|
fun bind(card: VisualDownloadHeaderCached) {
|
||||||
val d = card.data
|
val d = card.data
|
||||||
|
@ -77,9 +88,31 @@ class DownloadHeaderAdapter(
|
||||||
title.text = d.name
|
title.text = d.name
|
||||||
val mbString = "%.1f".format(card.totalBytes / 1000000f)
|
val mbString = "%.1f".format(card.totalBytes / 1000000f)
|
||||||
|
|
||||||
|
//val isMovie = d.type.isMovieType()
|
||||||
|
if (card.child != null) {
|
||||||
|
downloadBar.visibility = View.VISIBLE
|
||||||
|
downloadImage.visibility = View.VISIBLE
|
||||||
|
normalImage.visibility = View.GONE
|
||||||
|
|
||||||
|
setUpButton(
|
||||||
|
card.currentBytes,
|
||||||
|
card.totalBytes,
|
||||||
|
downloadBar,
|
||||||
|
downloadImage,
|
||||||
|
extraInfo,
|
||||||
|
card.child,
|
||||||
|
movieClickCallback
|
||||||
|
)
|
||||||
|
|
||||||
|
holder.setOnClickListener {
|
||||||
|
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
downloadBar.visibility = View.GONE
|
||||||
|
downloadImage.visibility = View.GONE
|
||||||
|
normalImage.visibility = View.VISIBLE
|
||||||
|
|
||||||
extraInfo.text =
|
extraInfo.text =
|
||||||
if (d.type.isMovieType())
|
|
||||||
"${mbString}MB" else
|
|
||||||
"${card.totalDownloads} Episode${if (card.totalDownloads == 1) "" else "s"} | ${mbString}MB"
|
"${card.totalDownloads} Episode${if (card.totalDownloads == 1) "" else "s"} | ${mbString}MB"
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
|
@ -88,3 +121,4 @@ class DownloadHeaderAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,11 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.lagradost.cloudstream3.TvType
|
||||||
|
import com.lagradost.cloudstream3.isMovieType
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStore.getFolderName
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
@ -38,11 +41,14 @@ class DownloadViewModel : ViewModel() {
|
||||||
fun updateList(context: Context) = viewModelScope.launch {
|
fun updateList(context: Context) = viewModelScope.launch {
|
||||||
val children = withContext(Dispatchers.IO) {
|
val children = withContext(Dispatchers.IO) {
|
||||||
val headers = context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
val headers = context.getKeys(DOWNLOAD_EPISODE_CACHE)
|
||||||
headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) }.distinctBy { it.id } // Remove duplicates
|
headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) }
|
||||||
|
.distinctBy { it.id } // Remove duplicates
|
||||||
}
|
}
|
||||||
|
|
||||||
// parentId : bytes
|
// parentId : bytes
|
||||||
val bytesUsedByChild = HashMap<Int, Long>()
|
val totalBytesUsedByChild = HashMap<Int, Long>()
|
||||||
|
// parentId : bytes
|
||||||
|
val currentBytesUsedByChild = HashMap<Int, Long>()
|
||||||
// parentId : downloadsCount
|
// parentId : downloadsCount
|
||||||
val totalDownloads = HashMap<Int, Int>()
|
val totalDownloads = HashMap<Int, Int>()
|
||||||
|
|
||||||
|
@ -53,17 +59,11 @@ class DownloadViewModel : ViewModel() {
|
||||||
|
|
||||||
if (childFile.fileLength <= 1) continue
|
if (childFile.fileLength <= 1) continue
|
||||||
val len = childFile.totalBytes
|
val len = childFile.totalBytes
|
||||||
if (bytesUsedByChild.containsKey(c.parentId)) {
|
val flen = childFile.fileLength
|
||||||
bytesUsedByChild[c.parentId] = bytesUsedByChild[c.parentId]?.plus(len) ?: len
|
|
||||||
} else {
|
|
||||||
bytesUsedByChild[c.parentId] = len
|
|
||||||
}
|
|
||||||
|
|
||||||
if (totalDownloads.containsKey(c.parentId)) {
|
totalBytesUsedByChild[c.parentId] = totalBytesUsedByChild[c.parentId]?.plus(len) ?: len
|
||||||
|
currentBytesUsedByChild[c.parentId] = currentBytesUsedByChild[c.parentId]?.plus(flen) ?: flen
|
||||||
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
||||||
} else {
|
|
||||||
totalDownloads[c.parentId] = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +75,21 @@ class DownloadViewModel : ViewModel() {
|
||||||
val visual = withContext(Dispatchers.IO) {
|
val visual = withContext(Dispatchers.IO) {
|
||||||
cached.mapNotNull { // TODO FIX
|
cached.mapNotNull { // TODO FIX
|
||||||
val downloads = totalDownloads[it.id] ?: 0
|
val downloads = totalDownloads[it.id] ?: 0
|
||||||
val bytes = bytesUsedByChild[it.id] ?: 0
|
val bytes = totalBytesUsedByChild[it.id] ?: 0
|
||||||
|
val currentBytes = currentBytesUsedByChild[it.id] ?: 0
|
||||||
if (bytes <= 0 || downloads <= 0) return@mapNotNull null
|
if (bytes <= 0 || downloads <= 0) return@mapNotNull null
|
||||||
VisualDownloadHeaderCached(0, downloads, bytes, it)
|
val movieEpisode = if (!it.type.isMovieType()) null else context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(
|
||||||
|
DOWNLOAD_EPISODE_CACHE,
|
||||||
|
getFolderName(it.id.toString(), it.id.toString())
|
||||||
|
)
|
||||||
|
VisualDownloadHeaderCached(
|
||||||
|
0,
|
||||||
|
downloads,
|
||||||
|
bytes,
|
||||||
|
currentBytes,
|
||||||
|
it,
|
||||||
|
movieEpisode
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,7 @@ class ResultFragment : Fragment() {
|
||||||
val meta = VideoDownloadManager.DownloadEpisodeMetadata(
|
val meta = VideoDownloadManager.DownloadEpisodeMetadata(
|
||||||
episodeClick.data.id,
|
episodeClick.data.id,
|
||||||
titleName,
|
titleName,
|
||||||
apiName ?: return,
|
apiName,
|
||||||
episodeClick.data.poster ?: currentPoster,
|
episodeClick.data.poster ?: currentPoster,
|
||||||
episodeClick.data.name,
|
episodeClick.data.name,
|
||||||
if (isMovie) null else episodeClick.data.season,
|
if (isMovie) null else episodeClick.data.season,
|
||||||
|
|
|
@ -171,7 +171,7 @@ class ResultViewModel : ViewModel() {
|
||||||
null,
|
null,
|
||||||
d.dataUrl,
|
d.dataUrl,
|
||||||
d.apiName,
|
d.apiName,
|
||||||
(mainId + 1),
|
(mainId), // HAS SAME ID
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -143,6 +143,7 @@ object VideoDownloadManager {
|
||||||
|
|
||||||
val downloadStatus = HashMap<Int, DownloadType>()
|
val downloadStatus = HashMap<Int, DownloadType>()
|
||||||
val downloadStatusEvent = Event<Pair<Int, DownloadType>>()
|
val downloadStatusEvent = Event<Pair<Int, DownloadType>>()
|
||||||
|
val downloadDeleteEvent = Event<Int>()
|
||||||
val downloadEvent = Event<Pair<Int, DownloadActionType>>()
|
val downloadEvent = Event<Pair<Int, DownloadActionType>>()
|
||||||
val downloadProgressEvent = Event<Triple<Int, Long, Long>>()
|
val downloadProgressEvent = Event<Triple<Int, Long, Long>>()
|
||||||
val downloadQueue = LinkedList<DownloadResumePackage>()
|
val downloadQueue = LinkedList<DownloadResumePackage>()
|
||||||
|
@ -427,6 +428,7 @@ object VideoDownloadManager {
|
||||||
} else {
|
} else {
|
||||||
if (!File(normalPath).delete()) return ERROR_DELETING_FILE
|
if (!File(normalPath).delete()) return ERROR_DELETING_FILE
|
||||||
}
|
}
|
||||||
|
downloadDeleteEvent.invoke(ep.id)
|
||||||
return SUCCESS_STOPPED
|
return SUCCESS_STOPPED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,10 +718,11 @@ object VideoDownloadManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteFile(context: Context, id: Int): Boolean {
|
private fun deleteFile(context: Context, id: Int): Boolean {
|
||||||
|
val info = context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return false
|
||||||
downloadEvent.invoke(Pair(id, DownloadActionType.Stop))
|
downloadEvent.invoke(Pair(id, DownloadActionType.Stop))
|
||||||
downloadProgressEvent.invoke(Triple(id, 0, 0))
|
downloadProgressEvent.invoke(Triple(id, 0, 0))
|
||||||
downloadStatusEvent.invoke(Pair(id, DownloadType.IsStopped))
|
downloadStatusEvent.invoke(Pair(id, DownloadType.IsStopped))
|
||||||
val info = context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return false
|
downloadDeleteEvent.invoke(id)
|
||||||
|
|
||||||
if (isScopedStorage()) {
|
if (isScopedStorage()) {
|
||||||
val cr = context.contentResolver ?: return false
|
val cr = context.contentResolver ?: return false
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="850.39dp"
|
android:width="24dp"
|
||||||
android:height="850.39dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="850.39"
|
android:viewportWidth="850.39"
|
||||||
android:viewportHeight="850.39">
|
android:viewportHeight="850.39">
|
||||||
<path
|
<path
|
||||||
|
|
|
@ -83,7 +83,8 @@
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:padding="2dp"
|
android:padding="2dp"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:id="@+id/download_child_episode_download"
|
android:id="@+id/download_child_episode_download"
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_marginEnd="50dp"
|
android:layout_marginEnd="70dp"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_header_title"
|
android:id="@+id/download_header_title"
|
||||||
|
@ -52,14 +52,49 @@
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
</TextView>
|
</TextView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<!--
|
|
||||||
android:background="?selectableItemBackgroundBorderless"-->
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_marginStart="-40dp"
|
android:layout_marginStart="-50dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
|
android:id="@+id/download_header_goto_child"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:layout_gravity="center_vertical|end"
|
||||||
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
|
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
|
||||||
android:contentDescription="@string/download_descript"/>
|
android:contentDescription="@string/download_descript"/>
|
||||||
|
|
||||||
|
<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_marginEnd="10dp"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="2dp"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:id="@+id/download_header_episode_download"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||||
|
android:contentDescription="@string/download_descript"/>
|
||||||
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -86,7 +86,8 @@
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:padding="2dp"
|
android:padding="2dp"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:id="@+id/result_episode_download"
|
android:id="@+id/result_episode_download"
|
||||||
|
|
|
@ -101,7 +101,8 @@
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
android:padding="2dp"
|
android:padding="2dp"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:id="@+id/result_episode_download"
|
android:id="@+id/result_episode_download"
|
||||||
|
@ -109,7 +110,6 @@
|
||||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||||
android:contentDescription="@string/download_descript"/>
|
android:contentDescription="@string/download_descript"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<TextView
|
<TextView
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
|
|
Loading…
Reference in a new issue