mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge adapters and support swipe to delete for episodes
This commit is contained in:
parent
5cfd98e4a4
commit
d4631bc838
7 changed files with 303 additions and 277 deletions
|
@ -0,0 +1,241 @@
|
||||||
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
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 androidx.viewbinding.ViewBinding
|
||||||
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.databinding.DownloadChildEpisodeBinding
|
||||||
|
import com.lagradost.cloudstream3.databinding.DownloadHeaderEpisodeBinding
|
||||||
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||||
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
|
||||||
|
|
||||||
|
const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
||||||
|
const val DOWNLOAD_ACTION_DELETE_FILE = 1
|
||||||
|
const val DOWNLOAD_ACTION_RESUME_DOWNLOAD = 2
|
||||||
|
const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3
|
||||||
|
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
||||||
|
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
||||||
|
|
||||||
|
abstract class VisualDownloadCachedAbstract(
|
||||||
|
open val currentBytes: Long,
|
||||||
|
open val totalBytes: Long,
|
||||||
|
open val data: VideoDownloadHelper.DownloadCachedAbstract
|
||||||
|
)
|
||||||
|
|
||||||
|
data class VisualDownloadChildCached(
|
||||||
|
override val currentBytes: Long,
|
||||||
|
override val totalBytes: Long,
|
||||||
|
override val data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||||
|
): VisualDownloadCachedAbstract(currentBytes, totalBytes, data)
|
||||||
|
|
||||||
|
data class VisualDownloadHeaderCached(
|
||||||
|
val currentOngoingDownloads: Int,
|
||||||
|
val totalDownloads: Int,
|
||||||
|
override val totalBytes: Long,
|
||||||
|
override val currentBytes: Long,
|
||||||
|
override val data: VideoDownloadHelper.DownloadHeaderCached,
|
||||||
|
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||||
|
): VisualDownloadCachedAbstract(currentBytes, totalBytes, data)
|
||||||
|
|
||||||
|
data class DownloadClickEvent(
|
||||||
|
val action: Int,
|
||||||
|
val data: VideoDownloadHelper.DownloadEpisodeCached
|
||||||
|
)
|
||||||
|
|
||||||
|
data class DownloadHeaderClickEvent(
|
||||||
|
val action: Int,
|
||||||
|
val data: VideoDownloadHelper.DownloadHeaderCached
|
||||||
|
)
|
||||||
|
|
||||||
|
class DownloadAdapter(
|
||||||
|
var cardList: MutableList<VisualDownloadCachedAbstract>,
|
||||||
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val VIEW_TYPE_HEADER = 0
|
||||||
|
private const val VIEW_TYPE_CHILD = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
return DownloadViewHolder(
|
||||||
|
binding = when (viewType) {
|
||||||
|
VIEW_TYPE_HEADER -> {
|
||||||
|
DownloadHeaderEpisodeBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
VIEW_TYPE_CHILD -> {
|
||||||
|
DownloadChildEpisodeBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException("Invalid view type")
|
||||||
|
},
|
||||||
|
clickCallback,
|
||||||
|
movieClickCallback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
when (holder) {
|
||||||
|
is DownloadViewHolder -> {
|
||||||
|
holder.bind(cardList[position])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var viewType = 0
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int {
|
||||||
|
if (viewType != 0) {
|
||||||
|
return viewType
|
||||||
|
}
|
||||||
|
|
||||||
|
val isEpisodeBased = cardList[position] !is VisualDownloadHeaderCached
|
||||||
|
return if (isEpisodeBased) VIEW_TYPE_CHILD else VIEW_TYPE_HEADER
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return cardList.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
class DownloadViewHolder(
|
||||||
|
private val binding: ViewBinding,
|
||||||
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
/*private val poster: ImageView? = itemView.download_header_poster
|
||||||
|
private val title: TextView = itemView.download_header_title
|
||||||
|
private val extraInfo: TextView = itemView.download_header_info
|
||||||
|
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")
|
||||||
|
fun bind(card: VisualDownloadCachedAbstract) {
|
||||||
|
when (binding) {
|
||||||
|
is DownloadHeaderEpisodeBinding -> binding.apply {
|
||||||
|
if (card !is VisualDownloadHeaderCached) return
|
||||||
|
val d = card.data
|
||||||
|
|
||||||
|
downloadHeaderPoster.apply {
|
||||||
|
setImage(d.poster)
|
||||||
|
setOnClickListener {
|
||||||
|
clickCallback.invoke(DownloadHeaderClickEvent(1, d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadHeaderTitle.text = d.name
|
||||||
|
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
||||||
|
|
||||||
|
//val isMovie = d.type.isMovieType()
|
||||||
|
if (card.child != null) {
|
||||||
|
//downloadHeaderProgressDownloaded.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
// downloadHeaderEpisodeDownload.visibility = View.VISIBLE
|
||||||
|
downloadHeaderGotoChild.visibility = View.GONE
|
||||||
|
|
||||||
|
downloadButton.setDefaultClickListener(
|
||||||
|
card.child,
|
||||||
|
downloadHeaderInfo,
|
||||||
|
movieClickCallback
|
||||||
|
)
|
||||||
|
downloadButton.isVisible = true
|
||||||
|
/* setUpButton(
|
||||||
|
card.currentBytes,
|
||||||
|
card.totalBytes,
|
||||||
|
downloadBar,
|
||||||
|
downloadImage,
|
||||||
|
extraInfo,
|
||||||
|
card.child,
|
||||||
|
movieClickCallback
|
||||||
|
) */
|
||||||
|
|
||||||
|
episodeHolder.setOnClickListener {
|
||||||
|
movieClickCallback.invoke(
|
||||||
|
DownloadClickEvent(
|
||||||
|
DOWNLOAD_ACTION_PLAY_FILE,
|
||||||
|
card.child
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
downloadButton.isVisible = false
|
||||||
|
// downloadHeaderProgressDownloaded.visibility = View.GONE
|
||||||
|
// downloadHeaderEpisodeDownload.visibility = View.GONE
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is DownloadChildEpisodeBinding -> binding.apply {
|
||||||
|
if (card !is VisualDownloadChildCached) return
|
||||||
|
val d = card.data
|
||||||
|
|
||||||
|
val posDur = DataStoreHelper.getViewPos(d.id)
|
||||||
|
downloadChildEpisodeProgress.apply {
|
||||||
|
if (posDur != null) {
|
||||||
|
val visualPos = posDur.fixVisual()
|
||||||
|
max = (visualPos.duration / 1000).toInt()
|
||||||
|
progress = (visualPos.position / 1000).toInt()
|
||||||
|
visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadButton.setDefaultClickListener(card.data, downloadChildEpisodeTextExtra, movieClickCallback)
|
||||||
|
|
||||||
|
downloadChildEpisodeText.apply {
|
||||||
|
text = context.getNameFull(d.name, d.episode, d.season)
|
||||||
|
isSelected = true // is needed for text repeating
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadChildEpisodeHolder.setOnClickListener {
|
||||||
|
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,94 +0,0 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.lagradost.cloudstream3.databinding.DownloadChildEpisodeBinding
|
|
||||||
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
|
|
||||||
|
|
||||||
const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
|
||||||
const val DOWNLOAD_ACTION_DELETE_FILE = 1
|
|
||||||
const val DOWNLOAD_ACTION_RESUME_DOWNLOAD = 2
|
|
||||||
const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3
|
|
||||||
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
|
||||||
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
|
||||||
|
|
||||||
data class VisualDownloadChildCached(
|
|
||||||
val currentBytes: Long,
|
|
||||||
val totalBytes: Long,
|
|
||||||
val data: VideoDownloadHelper.DownloadEpisodeCached,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class DownloadClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadEpisodeCached)
|
|
||||||
|
|
||||||
class DownloadChildAdapter(
|
|
||||||
var cardList: List<VisualDownloadChildCached>,
|
|
||||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
|
||||||
return DownloadChildViewHolder(
|
|
||||||
DownloadChildEpisodeBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
|
||||||
clickCallback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
|
||||||
when (holder) {
|
|
||||||
is DownloadChildViewHolder -> {
|
|
||||||
holder.bind(cardList[position])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return cardList.size
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadChildViewHolder
|
|
||||||
constructor(
|
|
||||||
val binding: DownloadChildEpisodeBinding,
|
|
||||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
|
||||||
|
|
||||||
/*private val title: TextView = itemView.download_child_episode_text
|
|
||||||
private val extraInfo: TextView = itemView.download_child_episode_text_extra
|
|
||||||
private val holder: CardView = itemView.download_child_episode_holder
|
|
||||||
private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress
|
|
||||||
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
|
|
||||||
private val downloadImage: ImageView = itemView.download_child_episode_download*/
|
|
||||||
|
|
||||||
|
|
||||||
fun bind(card: VisualDownloadChildCached) {
|
|
||||||
val d = card.data
|
|
||||||
|
|
||||||
val posDur = getViewPos(d.id)
|
|
||||||
binding.downloadChildEpisodeProgress.apply {
|
|
||||||
if (posDur != null) {
|
|
||||||
val visualPos = posDur.fixVisual()
|
|
||||||
max = (visualPos.duration / 1000).toInt()
|
|
||||||
progress = (visualPos.position / 1000).toInt()
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.downloadButton.setDefaultClickListener(card.data, binding.downloadChildEpisodeTextExtra, clickCallback)
|
|
||||||
|
|
||||||
binding.downloadChildEpisodeText.apply {
|
|
||||||
text = context.getNameFull(d.name, d.episode, d.season)
|
|
||||||
isSelected = true // is needed for text repeating
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.downloadChildEpisodeHolder.setOnClickListener {
|
|
||||||
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,12 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
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.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding
|
import com.lagradost.cloudstream3.databinding.FragmentChildDownloadsBinding
|
||||||
|
@ -51,6 +53,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
return localBinding.root//inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
return localBinding.root//inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun updateList(folder: String) = main {
|
private fun updateList(folder: String) = main {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
||||||
|
@ -68,8 +71,8 @@ class DownloadChildFragment : Fragment() {
|
||||||
return@main
|
return@main
|
||||||
}
|
}
|
||||||
|
|
||||||
(binding?.downloadChildList?.adapter as DownloadChildAdapter? ?: return@main).cardList =
|
(binding?.downloadChildList?.adapter as DownloadAdapter? ?: return@main).cardList =
|
||||||
eps
|
eps.toMutableList()
|
||||||
binding?.downloadChildList?.adapter?.notifyDataSetChanged()
|
binding?.downloadChildList?.adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,30 +102,47 @@ class DownloadChildFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
DownloadChildAdapter(
|
DownloadAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
) { click ->
|
{}
|
||||||
handleDownloadClick(click)
|
) { downloadClickEvent ->
|
||||||
}
|
handleDownloadClick(downloadClickEvent)
|
||||||
|
if (downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||||
|
downloadDeleteEventListener = { id: Int ->
|
||||||
|
val list =
|
||||||
|
(binding?.downloadChildList?.adapter as DownloadAdapter?)?.cardList
|
||||||
|
if (list != null) {
|
||||||
|
if (list.any { it.data.id == id }) {
|
||||||
|
updateList(folder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
downloadDeleteEventListener = { id: Int ->
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
||||||
val list = (binding?.downloadChildList?.adapter as DownloadChildAdapter?)?.cardList
|
|
||||||
if (list != null) {
|
|
||||||
if (list.any { it.data.id == id }) {
|
|
||||||
updateList(folder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding?.downloadChildList?.apply {
|
||||||
|
setHasFixedSize(true)
|
||||||
|
setItemViewCacheSize(20)
|
||||||
|
this.adapter = adapter
|
||||||
|
setLinearListLayout(
|
||||||
|
isHorizontal = false,
|
||||||
|
nextRight = FOCUS_SELF,
|
||||||
|
nextDown = FOCUS_SELF
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isLayout(PHONE or EMULATOR)) {
|
||||||
|
val itemTouchHelper = ItemTouchHelper(
|
||||||
|
DownloadSwipeDeleteCallback(
|
||||||
|
this.adapter as DownloadAdapter,
|
||||||
|
context ?: return@apply
|
||||||
|
)
|
||||||
|
)
|
||||||
|
itemTouchHelper.attachToRecyclerView(binding?.downloadChildList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it }
|
|
||||||
|
|
||||||
binding?.downloadChildList?.adapter = adapter
|
|
||||||
binding?.downloadChildList?.setLinearListLayout(
|
|
||||||
isHorizontal = false,
|
|
||||||
nextDown = FOCUS_SELF,
|
|
||||||
nextRight = FOCUS_SELF
|
|
||||||
)//layoutManager = GridLayoutManager(context, 1)
|
|
||||||
|
|
||||||
updateList(folder)
|
updateList(folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -46,7 +46,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setAppBarNoScrollFlagsOnTV
|
import com.lagradost.cloudstream3.utils.UIHelper.setAppBarNoScrollFlagsOnTV
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ class DownloadFragment : Fragment() {
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun setList(list: List<VisualDownloadHeaderCached>) {
|
private fun setList(list: List<VisualDownloadHeaderCached>) {
|
||||||
main {
|
main {
|
||||||
(binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.cardList = list.toMutableList()
|
(binding?.downloadList?.adapter as DownloadAdapter?)?.cardList = list.toMutableList()
|
||||||
binding?.downloadList?.adapter?.notifyDataSetChanged()
|
binding?.downloadList?.adapter?.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +87,7 @@ class DownloadFragment : Fragment() {
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View {
|
||||||
downloadsViewModel =
|
downloadsViewModel =
|
||||||
ViewModelProvider(this)[DownloadViewModel::class.java]
|
ViewModelProvider(this)[DownloadViewModel::class.java]
|
||||||
|
|
||||||
|
@ -143,7 +142,7 @@ class DownloadFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||||
DownloadHeaderAdapter(
|
DownloadAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
{ click ->
|
{ click ->
|
||||||
when (click.action) {
|
when (click.action) {
|
||||||
|
@ -172,11 +171,10 @@ class DownloadFragment : Fragment() {
|
||||||
|
|
||||||
},
|
},
|
||||||
{ downloadClickEvent ->
|
{ downloadClickEvent ->
|
||||||
if (downloadClickEvent.data !is VideoDownloadHelper.DownloadEpisodeCached) return@DownloadHeaderAdapter
|
|
||||||
handleDownloadClick(downloadClickEvent)
|
handleDownloadClick(downloadClickEvent)
|
||||||
if (downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
if (downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||||
downloadDeleteEventListener = { id ->
|
downloadDeleteEventListener = { id ->
|
||||||
val list = (binding?.downloadList?.adapter as DownloadHeaderAdapter?)?.cardList
|
val list = (binding?.downloadList?.adapter as DownloadAdapter?)?.cardList
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
if (list.any { it.data.id == id }) {
|
if (list.any { it.data.id == id }) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
|
@ -204,7 +202,7 @@ class DownloadFragment : Fragment() {
|
||||||
if (isLayout(PHONE or EMULATOR)) {
|
if (isLayout(PHONE or EMULATOR)) {
|
||||||
val itemTouchHelper = ItemTouchHelper(
|
val itemTouchHelper = ItemTouchHelper(
|
||||||
DownloadSwipeDeleteCallback(
|
DownloadSwipeDeleteCallback(
|
||||||
this.adapter as DownloadHeaderAdapter,
|
this.adapter as DownloadAdapter,
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
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
|
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
data class VisualDownloadHeaderCached(
|
|
||||||
val currentOngoingDownloads: Int,
|
|
||||||
val totalDownloads: Int,
|
|
||||||
val totalBytes: Long,
|
|
||||||
val currentBytes: Long,
|
|
||||||
val data: VideoDownloadHelper.DownloadHeaderCached,
|
|
||||||
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class DownloadHeaderClickEvent(
|
|
||||||
val action: Int,
|
|
||||||
val data: VideoDownloadHelper.DownloadHeaderCached
|
|
||||||
)
|
|
||||||
|
|
||||||
class DownloadHeaderAdapter(
|
|
||||||
var cardList: MutableList<VisualDownloadHeaderCached>,
|
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
|
||||||
return DownloadHeaderViewHolder(
|
|
||||||
DownloadHeaderEpisodeBinding.inflate(
|
|
||||||
LayoutInflater.from(parent.context),
|
|
||||||
parent,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
clickCallback,
|
|
||||||
movieClickCallback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
|
||||||
when (holder) {
|
|
||||||
is DownloadHeaderViewHolder -> {
|
|
||||||
holder.bind(cardList[position])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return cardList.count()
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadHeaderViewHolder
|
|
||||||
constructor(
|
|
||||||
val binding: DownloadHeaderEpisodeBinding,
|
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
|
||||||
|
|
||||||
/*private val poster: ImageView? = itemView.download_header_poster
|
|
||||||
private val title: TextView = itemView.download_header_title
|
|
||||||
private val extraInfo: TextView = itemView.download_header_info
|
|
||||||
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")
|
|
||||||
fun bind(card: VisualDownloadHeaderCached) {
|
|
||||||
val d = card.data
|
|
||||||
|
|
||||||
binding.downloadHeaderPoster.apply {
|
|
||||||
setImage(d.poster)
|
|
||||||
setOnClickListener {
|
|
||||||
clickCallback.invoke(DownloadHeaderClickEvent(1, d))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.apply {
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
// downloadHeaderEpisodeDownload.visibility = View.VISIBLE
|
|
||||||
binding.downloadHeaderGotoChild.visibility = View.GONE
|
|
||||||
|
|
||||||
downloadButton.setDefaultClickListener(card.child, downloadHeaderInfo, movieClickCallback)
|
|
||||||
downloadButton.isVisible = true
|
|
||||||
/*setUpButton(
|
|
||||||
card.currentBytes,
|
|
||||||
card.totalBytes,
|
|
||||||
downloadBar,
|
|
||||||
downloadImage,
|
|
||||||
extraInfo,
|
|
||||||
card.child,
|
|
||||||
movieClickCallback
|
|
||||||
)*/
|
|
||||||
|
|
||||||
episodeHolder.setOnClickListener {
|
|
||||||
movieClickCallback.invoke(
|
|
||||||
DownloadClickEvent(
|
|
||||||
DOWNLOAD_ACTION_PLAY_FILE,
|
|
||||||
card.child
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,10 +16,11 @@ import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.isEpisodeBased
|
import com.lagradost.cloudstream3.isEpisodeBased
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
|
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.downloadDeleteEvent
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.downloadDeleteEvent
|
||||||
|
|
||||||
class DownloadSwipeDeleteCallback(
|
class DownloadSwipeDeleteCallback(
|
||||||
private val adapter: DownloadHeaderAdapter,
|
private val adapter: DownloadAdapter,
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) : ItemTouchHelper.Callback() {
|
) : ItemTouchHelper.Callback() {
|
||||||
|
|
||||||
|
@ -39,10 +40,12 @@ class DownloadSwipeDeleteCallback(
|
||||||
recyclerView: RecyclerView,
|
recyclerView: RecyclerView,
|
||||||
viewHolder: RecyclerView.ViewHolder
|
viewHolder: RecyclerView.ViewHolder
|
||||||
): Int {
|
): Int {
|
||||||
|
val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
|
||||||
|
|
||||||
val position = viewHolder.bindingAdapterPosition
|
val position = viewHolder.bindingAdapterPosition
|
||||||
val item = adapter.cardList[position]
|
val item = adapter.cardList[position]
|
||||||
|
if (item !is VisualDownloadHeaderCached) return makeMovementFlags(0, swipeFlags)
|
||||||
return if (item.data.type.isEpisodeBased()) 0 else {
|
return if (item.data.type.isEpisodeBased()) 0 else {
|
||||||
val swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
|
|
||||||
makeMovementFlags(0, swipeFlags)
|
makeMovementFlags(0, swipeFlags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +199,10 @@ class DownloadSwipeDeleteCallback(
|
||||||
private fun handleDeleteAction(position: Int) {
|
private fun handleDeleteAction(position: Int) {
|
||||||
val item = adapter.cardList[position]
|
val item = adapter.cardList[position]
|
||||||
runOnMainThread {
|
runOnMainThread {
|
||||||
item.child?.let { clickEvent ->
|
val data: VideoDownloadHelper.DownloadEpisodeCached? = if (item is VisualDownloadHeaderCached) item.child else {
|
||||||
|
item.data as VideoDownloadHelper.DownloadEpisodeCached?
|
||||||
|
}
|
||||||
|
data?.let { clickEvent ->
|
||||||
handleDownloadClick(
|
handleDownloadClick(
|
||||||
DownloadClickEvent(
|
DownloadClickEvent(
|
||||||
DOWNLOAD_ACTION_DELETE_FILE,
|
DOWNLOAD_ACTION_DELETE_FILE,
|
||||||
|
|
|
@ -3,17 +3,21 @@ package com.lagradost.cloudstream3.utils
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
object VideoDownloadHelper {
|
object VideoDownloadHelper {
|
||||||
|
abstract class DownloadCachedAbstract(
|
||||||
|
@JsonProperty("id") open val id: Int,
|
||||||
|
)
|
||||||
|
|
||||||
data class DownloadEpisodeCached(
|
data class DownloadEpisodeCached(
|
||||||
@JsonProperty("name") val name: String?,
|
@JsonProperty("name") val name: String?,
|
||||||
@JsonProperty("poster") val poster: String?,
|
@JsonProperty("poster") val poster: String?,
|
||||||
@JsonProperty("episode") val episode: Int,
|
@JsonProperty("episode") val episode: Int,
|
||||||
@JsonProperty("season") val season: Int?,
|
@JsonProperty("season") val season: Int?,
|
||||||
@JsonProperty("id") val id: Int,
|
@JsonProperty("id") override val id: Int,
|
||||||
@JsonProperty("parentId") val parentId: Int,
|
@JsonProperty("parentId") val parentId: Int,
|
||||||
@JsonProperty("rating") val rating: Int?,
|
@JsonProperty("rating") val rating: Int?,
|
||||||
@JsonProperty("description") val description: String?,
|
@JsonProperty("description") val description: String?,
|
||||||
@JsonProperty("cacheTime") val cacheTime: Long,
|
@JsonProperty("cacheTime") val cacheTime: Long,
|
||||||
)
|
): DownloadCachedAbstract(id)
|
||||||
|
|
||||||
data class DownloadHeaderCached(
|
data class DownloadHeaderCached(
|
||||||
@JsonProperty("apiName") val apiName: String,
|
@JsonProperty("apiName") val apiName: String,
|
||||||
|
@ -21,9 +25,9 @@ object VideoDownloadHelper {
|
||||||
@JsonProperty("type") val type: TvType,
|
@JsonProperty("type") val type: TvType,
|
||||||
@JsonProperty("name") val name: String,
|
@JsonProperty("name") val name: String,
|
||||||
@JsonProperty("poster") val poster: String?,
|
@JsonProperty("poster") val poster: String?,
|
||||||
@JsonProperty("id") val id: Int,
|
@JsonProperty("id") override val id: Int,
|
||||||
@JsonProperty("cacheTime") val cacheTime: Long,
|
@JsonProperty("cacheTime") val cacheTime: Long,
|
||||||
)
|
): DownloadCachedAbstract(id)
|
||||||
|
|
||||||
data class ResumeWatching(
|
data class ResumeWatching(
|
||||||
@JsonProperty("parentId") val parentId: Int,
|
@JsonProperty("parentId") val parentId: Int,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue