mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue