mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	fixed mem leak
This commit is contained in:
		
							parent
							
								
									8ff87e5108
								
							
						
					
					
						commit
						f270f9f551
					
				
					 12 changed files with 427 additions and 227 deletions
				
			
		|  | @ -1,24 +1,13 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.animation.ObjectAnimator | ||||
| import android.annotation.SuppressLint | ||||
| import android.app.Activity | ||||
| import android.content.DialogInterface | ||||
| import android.view.View | ||||
| import android.view.animation.DecelerateInterpolator | ||||
| import android.widget.ImageView | ||||
| import android.widget.TextView | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||
| import com.lagradost.cloudstream3.ui.player.UriData | ||||
| import com.lagradost.cloudstream3.utils.Coroutines | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| 
 | ||||
| object DownloadButtonSetup { | ||||
|  | @ -95,167 +84,4 @@ object DownloadButtonSetup { | |||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun setUpDownloadButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         downloadView: View, | ||||
|         downloadImageChangeCallback: (Pair<Int, String>) -> Unit, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ): () -> Unit { | ||||
|         var lastState: VideoDownloadManager.DownloadType? = null | ||||
|         var currentBytes = setupCurrentBytes ?: 0 | ||||
|         var totalBytes = setupTotalBytes ?: 0 | ||||
|         var needImageUpdate = false | ||||
| 
 | ||||
|         fun changeDownloadImage(state: VideoDownloadManager.DownloadType) { | ||||
|             lastState = state | ||||
|             if (currentBytes <= 0) needImageUpdate = true | ||||
|             val img = if (currentBytes > 0) { | ||||
|                 when (state) { | ||||
|                     VideoDownloadManager.DownloadType.IsPaused -> Pair( | ||||
|                         R.drawable.ic_baseline_play_arrow_24, | ||||
|                         "Download Paused" | ||||
|                     ) | ||||
|                     VideoDownloadManager.DownloadType.IsDownloading -> Pair(R.drawable.netflix_pause, "Downloading") | ||||
|                     else -> Pair(R.drawable.ic_baseline_delete_outline_24, "Downloaded") | ||||
|                 } | ||||
|             } else { | ||||
|                 Pair(R.drawable.netflix_download, "Download") | ||||
|             } | ||||
|             downloadImageChangeCallback.invoke(img) | ||||
|         } | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun fixDownloadedBytes(setCurrentBytes: Long, setTotalBytes: Long, animate: Boolean) { | ||||
|             currentBytes = setCurrentBytes | ||||
|             totalBytes = setTotalBytes | ||||
| 
 | ||||
|             if (currentBytes == 0L) { | ||||
|                 changeDownloadImage(VideoDownloadManager.DownloadType.IsStopped) | ||||
|                 textView?.visibility = View.GONE | ||||
|                 progressBar?.visibility = View.GONE | ||||
|             } else { | ||||
|                 if (lastState == VideoDownloadManager.DownloadType.IsStopped) { | ||||
|                     changeDownloadImage(VideoDownloadManager.getDownloadState(data.id)) | ||||
|                 } | ||||
|                 textView?.visibility = View.VISIBLE | ||||
|                 progressBar?.visibility = View.VISIBLE | ||||
|                 val currentMbString = "%.1f".format(setCurrentBytes / 1000000f) | ||||
|                 val totalMbString = "%.1f".format(setTotalBytes / 1000000f) | ||||
| 
 | ||||
|                 textView?.text = | ||||
|                     "${currentMbString}MB / ${totalMbString}MB" | ||||
| 
 | ||||
|                 progressBar?.let { bar -> | ||||
|                     bar.max = (setTotalBytes / 1000).toInt() | ||||
| 
 | ||||
|                     if (animate) { | ||||
|                         val animation: ObjectAnimator = ObjectAnimator.ofInt( | ||||
|                             bar, | ||||
|                             "progress", | ||||
|                             bar.progress, | ||||
|                             (setCurrentBytes / 1000).toInt() | ||||
|                         ) | ||||
|                         animation.duration = 500 | ||||
|                         animation.setAutoCancel(true) | ||||
|                         animation.interpolator = DecelerateInterpolator() | ||||
|                         animation.start() | ||||
|                     } else { | ||||
|                         bar.progress = (setCurrentBytes / 1000).toInt() | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         fixDownloadedBytes(currentBytes, totalBytes, false) | ||||
|         changeDownloadImage(VideoDownloadManager.getDownloadState(data.id)) | ||||
| 
 | ||||
|         val downloadProgressEventListener = { downloadData: Triple<Int, Long, Long> -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (downloadData.second != currentBytes || downloadData.third != totalBytes) { // TO PREVENT WASTING UI TIME | ||||
|                     Coroutines.runOnMainThread { | ||||
|                         fixDownloadedBytes(downloadData.second, downloadData.third, true) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val downloadStatusEventListener = { downloadData: Pair<Int, VideoDownloadManager.DownloadType> -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (lastState != downloadData.second || needImageUpdate) { // TO PREVENT WASTING UI TIME | ||||
|                     Coroutines.runOnMainThread { | ||||
|                         changeDownloadImage(downloadData.second) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         VideoDownloadManager.downloadProgressEvent += downloadProgressEventListener | ||||
|         VideoDownloadManager.downloadStatusEvent += downloadStatusEventListener | ||||
| 
 | ||||
|         downloadView.setOnClickListener { | ||||
|             if (currentBytes <= 0) { | ||||
|                 clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) | ||||
|             } else { | ||||
|                 val list = arrayListOf( | ||||
|                     Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file), | ||||
|                     Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file), | ||||
|                 ) | ||||
| 
 | ||||
|                 // DON'T RESUME A DOWNLOADED FILE lastState != VideoDownloadManager.DownloadType.IsDone && | ||||
|                 if ((currentBytes * 100 / totalBytes) < 98) { | ||||
|                     list.add( | ||||
|                         if (lastState == VideoDownloadManager.DownloadType.IsDownloading) | ||||
|                             Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download) | ||||
|                         else | ||||
|                             Pair(DOWNLOAD_ACTION_RESUME_DOWNLOAD, R.string.popup_resume_download) | ||||
|                     ) | ||||
|                 } | ||||
| 
 | ||||
|                 it.popupMenuNoIcons( | ||||
|                     list | ||||
|                 ) { | ||||
|                     clickCallback.invoke(DownloadClickEvent(itemId, data)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return { | ||||
|             VideoDownloadManager.downloadProgressEvent -= downloadProgressEventListener | ||||
|             VideoDownloadManager.downloadStatusEvent -= downloadStatusEventListener | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun setUpMaterialButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         downloadButton: MaterialButton, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ): () -> Unit { | ||||
|         return setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadButton, { | ||||
|             downloadButton?.setIconResource(it.first) | ||||
|             downloadButton?.text = it.second | ||||
|         }, clickCallback) | ||||
|     } | ||||
| 
 | ||||
|     fun setUpButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         downloadImage: ImageView, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ): () -> Unit { | ||||
|         return setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadImage, { | ||||
|             downloadImage?.setImageResource(it.first) | ||||
|         }, clickCallback) | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| interface DownloadButtonViewHolder { | ||||
|     var downloadButton : EasyDownloadButton | ||||
|     fun reattachDownloadButton() | ||||
| } | ||||
|  | @ -1,28 +1,20 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.animation.ObjectAnimator | ||||
| import android.annotation.SuppressLint | ||||
| import android.os.Handler | ||||
| import android.os.Looper | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.view.animation.DecelerateInterpolator | ||||
| import android.widget.ImageView | ||||
| import android.widget.ProgressBar | ||||
| import android.widget.TextView | ||||
| import androidx.cardview.widget.CardView | ||||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager.getDownloadState | ||||
| import kotlinx.android.synthetic.main.download_child_episode.view.* | ||||
| import java.util.* | ||||
| 
 | ||||
| const val DOWNLOAD_ACTION_PLAY_FILE = 0 | ||||
| const val DOWNLOAD_ACTION_DELETE_FILE = 1 | ||||
|  | @ -41,8 +33,37 @@ data class DownloadClickEvent(val action: Int, val data: VideoDownloadHelper.Dow | |||
| class DownloadChildAdapter( | ||||
|     var cardList: List<VisualDownloadChildCached>, | ||||
|     private val clickCallback: (DownloadClickEvent) -> Unit, | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| 
 | ||||
|     private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet() | ||||
|     private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? { | ||||
|         return Collections.unmodifiableSet(mBoundViewHolders) | ||||
|     } | ||||
| 
 | ||||
|     fun killAdapter() { | ||||
|         getAllBoundViewHolders()?.forEach { view -> | ||||
|             view?.downloadButton?.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewRecycled(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|             mBoundViewHolders.remove(holder); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.reattachDownloadButton() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|         return DownloadChildViewHolder( | ||||
|  | @ -55,6 +76,7 @@ class DownloadChildAdapter( | |||
|         when (holder) { | ||||
|             is DownloadChildViewHolder -> { | ||||
|                 holder.bind(cardList[position]) | ||||
|                 mBoundViewHolders.add(holder) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -67,7 +89,9 @@ class DownloadChildAdapter( | |||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|     ) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { | ||||
|         override var downloadButton = EasyDownloadButton() | ||||
| 
 | ||||
|         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 | ||||
|  | @ -75,8 +99,11 @@ class DownloadChildAdapter( | |||
|         private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded | ||||
|         private val downloadImage: ImageView = itemView.download_child_episode_download | ||||
| 
 | ||||
|         var localCard :  VisualDownloadChildCached? = null | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun bind(card: VisualDownloadChildCached) { | ||||
|             localCard = card | ||||
|             val d = card.data | ||||
| 
 | ||||
|             val posDur = itemView.context.getViewPos(d.id) | ||||
|  | @ -90,7 +117,7 @@ class DownloadChildAdapter( | |||
|             } | ||||
| 
 | ||||
|             title.text = d.name ?: "Episode ${d.episode}" //TODO FIX | ||||
|             DownloadButtonSetup.setUpButton( | ||||
|             downloadButton.setUpButton( | ||||
|                 card.currentBytes, | ||||
|                 card.totalBytes, | ||||
|                 progressBarDownload, | ||||
|  | @ -104,5 +131,21 @@ class DownloadChildAdapter( | |||
|                 clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d)) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         override fun reattachDownloadButton() { | ||||
|             downloadButton.dispose() | ||||
|             val card = localCard | ||||
|             if (card != null) { | ||||
|                 downloadButton.setUpButton( | ||||
|                     card.currentBytes, | ||||
|                     card.totalBytes, | ||||
|                     progressBarDownload, | ||||
|                     downloadImage, | ||||
|                     extraInfo, | ||||
|                     card.data, | ||||
|                     clickCallback | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -30,6 +30,16 @@ class DownloadChildFragment : Fragment() { | |||
|             } | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroyView() { | ||||
|         (download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it } | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_child_downloads, container, false) | ||||
|     } | ||||
|  | @ -58,6 +68,8 @@ class DownloadChildFragment : Fragment() { | |||
|         download_child_list?.adapter?.notifyDataSetChanged() | ||||
|     } | ||||
| 
 | ||||
|     var downloadDeleteEventListener: ((Int) -> Unit)? = null | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|  | @ -82,7 +94,7 @@ class DownloadChildFragment : Fragment() { | |||
|                 handleDownloadClick(activity, name, click) | ||||
|             } | ||||
| 
 | ||||
|         VideoDownloadManager.downloadDeleteEvent += { id -> | ||||
|         downloadDeleteEventListener = { id: Int -> | ||||
|             val list = (download_child_list?.adapter as DownloadChildAdapter?)?.cardList | ||||
|             if (list != null) { | ||||
|                 if (list.any { it.data.id == id }) { | ||||
|  | @ -91,6 +103,8 @@ class DownloadChildFragment : Fragment() { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it } | ||||
| 
 | ||||
|         download_child_list.adapter = adapter | ||||
|         download_child_list.layoutManager = GridLayoutManager(context, 1) | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,19 +11,15 @@ import androidx.lifecycle.ViewModelProvider | |||
| import androidx.navigation.findNavController | ||||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.MainActivity | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.isMovieType | ||||
| 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.utils.DOWNLOAD_EPISODE_CACHE | ||||
| 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_result.* | ||||
| 
 | ||||
| class DownloadFragment : Fragment() { | ||||
|     private lateinit var downloadsViewModel: DownloadViewModel | ||||
|  | @ -41,9 +37,19 @@ class DownloadFragment : Fragment() { | |||
|         this.layoutParams = param | ||||
|     } | ||||
| 
 | ||||
|     fun setList(list : List<VisualDownloadHeaderCached>) { | ||||
|         (download_list?.adapter as DownloadHeaderAdapter? ?: return).cardList = list | ||||
|         (download_list?.adapter as DownloadHeaderAdapter? ?: return).notifyDataSetChanged() | ||||
|     private fun setList(list: List<VisualDownloadHeaderCached>) { | ||||
|         (download_list?.adapter as DownloadHeaderAdapter?)?.cardList = list | ||||
|         download_list?.adapter?.notifyDataSetChanged() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroyView() { | ||||
|         (download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it } | ||||
|         super.onDestroy() | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("SetTextI18n") | ||||
|  | @ -76,6 +82,8 @@ class DownloadFragment : Fragment() { | |||
|         return inflater.inflate(R.layout.fragment_downloads, container, false) | ||||
|     } | ||||
| 
 | ||||
|     var downloadDeleteEventListener: ((Int) -> Unit)? = null | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|         val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = | ||||
|  | @ -95,13 +103,13 @@ class DownloadFragment : Fragment() { | |||
|                 }, | ||||
|                 { downloadClickEvent -> | ||||
|                     handleDownloadClick(activity, downloadClickEvent.data.name, downloadClickEvent) | ||||
|                     if(downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) { | ||||
|                     if (downloadClickEvent.action == DOWNLOAD_ACTION_DELETE_FILE) { | ||||
|                         downloadsViewModel.updateList(requireContext()) | ||||
|                     } | ||||
|                 } | ||||
|             ) | ||||
| 
 | ||||
|         VideoDownloadManager.downloadDeleteEvent += { id -> | ||||
|         downloadDeleteEventListener = { id -> | ||||
|             val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList | ||||
|             if (list != null) { | ||||
|                 if (list.any { it.data.id == id }) { | ||||
|  | @ -111,6 +119,8 @@ class DownloadFragment : Fragment() { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent += it } | ||||
| 
 | ||||
|         download_list.adapter = adapter | ||||
|         download_list.layoutManager = GridLayoutManager(context, 1) | ||||
|         downloadsViewModel.updateList(requireContext()) | ||||
|  |  | |||
|  | @ -12,10 +12,10 @@ import androidx.recyclerview.widget.RecyclerView | |||
| import com.bumptech.glide.Glide | ||||
| import com.bumptech.glide.load.model.GlideUrl | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.isMovieType | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.setUpButton | ||||
| import com.lagradost.cloudstream3.utils.IDisposable | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import kotlinx.android.synthetic.main.download_header_episode.view.* | ||||
| import java.util.* | ||||
| 
 | ||||
| data class VisualDownloadHeaderCached( | ||||
|     val currentOngoingDownloads: Int, | ||||
|  | @ -32,8 +32,37 @@ class DownloadHeaderAdapter( | |||
|     var cardList: List<VisualDownloadHeaderCached>, | ||||
|     private val clickCallback: (DownloadHeaderClickEvent) -> Unit, | ||||
|     private val movieClickCallback: (DownloadClickEvent) -> Unit, | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| 
 | ||||
|     private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet() | ||||
|     private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? { | ||||
|         return Collections.unmodifiableSet(mBoundViewHolders) | ||||
|     } | ||||
| 
 | ||||
|     fun killAdapter() { | ||||
|         getAllBoundViewHolders()?.forEach { view -> | ||||
|             view?.downloadButton?.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewRecycled(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|             mBoundViewHolders.remove(holder); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.reattachDownloadButton() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|         return DownloadHeaderViewHolder( | ||||
|  | @ -47,6 +76,7 @@ class DownloadHeaderAdapter( | |||
|         when (holder) { | ||||
|             is DownloadHeaderViewHolder -> { | ||||
|                 holder.bind(cardList[position]) | ||||
|                 mBoundViewHolders.add(holder) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -60,7 +90,9 @@ class DownloadHeaderAdapter( | |||
|         itemView: View, | ||||
|         private val clickCallback: (DownloadHeaderClickEvent) -> Unit, | ||||
|         private val movieClickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|     ) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { | ||||
|         override var downloadButton = EasyDownloadButton() | ||||
| 
 | ||||
|         private val poster: ImageView = itemView.download_header_poster | ||||
|         private val title: TextView = itemView.download_header_title | ||||
|         private val extraInfo: TextView = itemView.download_header_info | ||||
|  | @ -69,9 +101,11 @@ class DownloadHeaderAdapter( | |||
|         private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded | ||||
|         private val downloadImage: ImageView = itemView.download_header_episode_download | ||||
|         private val normalImage: ImageView = itemView.download_header_goto_child | ||||
|         var localCard: VisualDownloadHeaderCached? = null | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun bind(card: VisualDownloadHeaderCached) { | ||||
|             localCard = card | ||||
|             val d = card.data | ||||
|             if (d.poster != null) { | ||||
| 
 | ||||
|  | @ -93,8 +127,7 @@ class DownloadHeaderAdapter( | |||
|                 downloadBar.visibility = View.VISIBLE | ||||
|                 downloadImage.visibility = View.VISIBLE | ||||
|                 normalImage.visibility = View.GONE | ||||
| 
 | ||||
|                 setUpButton( | ||||
|                 /*setUpButton( | ||||
|                     card.currentBytes, | ||||
|                     card.totalBytes, | ||||
|                     downloadBar, | ||||
|  | @ -102,7 +135,7 @@ class DownloadHeaderAdapter( | |||
|                     extraInfo, | ||||
|                     card.child, | ||||
|                     movieClickCallback | ||||
|                 ) | ||||
|                 )*/ | ||||
| 
 | ||||
|                 holder.setOnClickListener { | ||||
|                     movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child)) | ||||
|  | @ -120,5 +153,21 @@ class DownloadHeaderAdapter( | |||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         override fun reattachDownloadButton() { | ||||
|             downloadButton.dispose() | ||||
|             val card = localCard | ||||
|             if (card?.child != null) { | ||||
|                 downloadButton.setUpButton( | ||||
|                     card.currentBytes, | ||||
|                     card.totalBytes, | ||||
|                     downloadBar, | ||||
|                     downloadImage, | ||||
|                     extraInfo, | ||||
|                     card.child, | ||||
|                     movieClickCallback | ||||
|                 ) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,188 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.animation.ObjectAnimator | ||||
| import android.annotation.SuppressLint | ||||
| import android.view.View | ||||
| import android.view.animation.DecelerateInterpolator | ||||
| import android.widget.ImageView | ||||
| import android.widget.TextView | ||||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import com.google.android.material.button.MaterialButton | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons | ||||
| import com.lagradost.cloudstream3.utils.Coroutines | ||||
| import com.lagradost.cloudstream3.utils.IDisposable | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| 
 | ||||
| class EasyDownloadButton : IDisposable { | ||||
|     override fun dispose() { | ||||
|         try { | ||||
|             downloadProgressEventListener?.let { VideoDownloadManager.downloadProgressEvent -= it } | ||||
|             downloadStatusEventListener?.let { VideoDownloadManager.downloadStatusEvent -= it } | ||||
|         } catch (e: Exception) { | ||||
|             e.printStackTrace() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     var downloadProgressEventListener: ((Triple<Int, Long, Long>) -> Unit)? = null | ||||
|     var downloadStatusEventListener: ((Pair<Int, VideoDownloadManager.DownloadType>) -> Unit)? = null | ||||
| 
 | ||||
|     fun setUpMaterialButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         downloadButton: MaterialButton, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) { | ||||
|         setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadButton, { | ||||
|             downloadButton?.setIconResource(it.first) | ||||
|             downloadButton?.text = it.second | ||||
|         }, clickCallback) | ||||
|     } | ||||
| 
 | ||||
|     fun setUpButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         downloadImage: ImageView, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) { | ||||
|         setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadImage, { | ||||
|             downloadImage?.setImageResource(it.first) | ||||
|         }, clickCallback) | ||||
|     } | ||||
| 
 | ||||
|     fun setUpDownloadButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         downloadView: View, | ||||
|         downloadImageChangeCallback: (Pair<Int, String>) -> Unit, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) { | ||||
|         var lastState: VideoDownloadManager.DownloadType? = null | ||||
|         var currentBytes = setupCurrentBytes ?: 0 | ||||
|         var totalBytes = setupTotalBytes ?: 0 | ||||
|         var needImageUpdate = false | ||||
| 
 | ||||
|         fun changeDownloadImage(state: VideoDownloadManager.DownloadType) { | ||||
|             lastState = state | ||||
|             if (currentBytes <= 0) needImageUpdate = true | ||||
|             val img = if (currentBytes > 0) { | ||||
|                 when (state) { | ||||
|                     VideoDownloadManager.DownloadType.IsPaused -> Pair( | ||||
|                         R.drawable.ic_baseline_play_arrow_24, | ||||
|                         "Download Paused" | ||||
|                     ) | ||||
|                     VideoDownloadManager.DownloadType.IsDownloading -> Pair(R.drawable.netflix_pause, "Downloading") | ||||
|                     else -> Pair(R.drawable.ic_baseline_delete_outline_24, "Downloaded") | ||||
|                 } | ||||
|             } else { | ||||
|                 Pair(R.drawable.netflix_download, "Download") | ||||
|             } | ||||
|             downloadImageChangeCallback.invoke(img) | ||||
|         } | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun fixDownloadedBytes(setCurrentBytes: Long, setTotalBytes: Long, animate: Boolean) { | ||||
|             currentBytes = setCurrentBytes | ||||
|             totalBytes = setTotalBytes | ||||
| 
 | ||||
|             if (currentBytes == 0L) { | ||||
|                 changeDownloadImage(VideoDownloadManager.DownloadType.IsStopped) | ||||
|                 textView?.visibility = View.GONE | ||||
|                 progressBar?.visibility = View.GONE | ||||
|             } else { | ||||
|                 if (lastState == VideoDownloadManager.DownloadType.IsStopped) { | ||||
|                     changeDownloadImage(VideoDownloadManager.getDownloadState(data.id)) | ||||
|                 } | ||||
|                 textView?.visibility = View.VISIBLE | ||||
|                 progressBar?.visibility = View.VISIBLE | ||||
|                 val currentMbString = "%.1f".format(setCurrentBytes / 1000000f) | ||||
|                 val totalMbString = "%.1f".format(setTotalBytes / 1000000f) | ||||
| 
 | ||||
|                 textView?.text = | ||||
|                     "${currentMbString}MB / ${totalMbString}MB" | ||||
| 
 | ||||
|                 progressBar?.let { bar -> | ||||
|                     bar.max = (setTotalBytes / 1000).toInt() | ||||
| 
 | ||||
|                     if (animate) { | ||||
|                         val animation: ObjectAnimator = ObjectAnimator.ofInt( | ||||
|                             bar, | ||||
|                             "progress", | ||||
|                             bar.progress, | ||||
|                             (setCurrentBytes / 1000).toInt() | ||||
|                         ) | ||||
|                         animation.duration = 500 | ||||
|                         animation.setAutoCancel(true) | ||||
|                         animation.interpolator = DecelerateInterpolator() | ||||
|                         animation.start() | ||||
|                     } else { | ||||
|                         bar.progress = (setCurrentBytes / 1000).toInt() | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         fixDownloadedBytes(currentBytes, totalBytes, false) | ||||
|         changeDownloadImage(VideoDownloadManager.getDownloadState(data.id)) | ||||
| 
 | ||||
|         downloadProgressEventListener = { downloadData: Triple<Int, Long, Long> -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (downloadData.second != currentBytes || downloadData.third != totalBytes) { // TO PREVENT WASTING UI TIME | ||||
|                     Coroutines.runOnMainThread { | ||||
|                         fixDownloadedBytes(downloadData.second, downloadData.third, true) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         downloadStatusEventListener = { downloadData: Pair<Int, VideoDownloadManager.DownloadType> -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (lastState != downloadData.second || needImageUpdate) { // TO PREVENT WASTING UI TIME | ||||
|                     Coroutines.runOnMainThread { | ||||
|                         changeDownloadImage(downloadData.second) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         downloadProgressEventListener?.let { VideoDownloadManager.downloadProgressEvent += it } | ||||
|         downloadStatusEventListener?.let { VideoDownloadManager.downloadStatusEvent += it } | ||||
| 
 | ||||
|         downloadView.setOnClickListener { | ||||
|             if (currentBytes <= 0) { | ||||
|                 clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) | ||||
|             } else { | ||||
|                 val list = arrayListOf( | ||||
|                     Pair(DOWNLOAD_ACTION_PLAY_FILE, R.string.popup_play_file), | ||||
|                     Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file), | ||||
|                 ) | ||||
| 
 | ||||
|                 // DON'T RESUME A DOWNLOADED FILE lastState != VideoDownloadManager.DownloadType.IsDone && | ||||
|                 if ((currentBytes * 100 / totalBytes) < 98) { | ||||
|                     list.add( | ||||
|                         if (lastState == VideoDownloadManager.DownloadType.IsDownloading) | ||||
|                             Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download) | ||||
|                         else | ||||
|                             Pair(DOWNLOAD_ACTION_RESUME_DOWNLOAD, R.string.popup_resume_download) | ||||
|                     ) | ||||
|                 } | ||||
| 
 | ||||
|                 it.popupMenuNoIcons( | ||||
|                     list | ||||
|                 ) { | ||||
|                     clickCallback.invoke(DownloadClickEvent(itemId, data)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -13,15 +13,15 @@ import com.bumptech.glide.Glide | |||
| import com.bumptech.glide.load.model.GlideUrl | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadClickEvent | ||||
| import com.lagradost.cloudstream3.utils.Event | ||||
| import com.lagradost.cloudstream3.ui.download.EasyDownloadButton | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| import kotlinx.android.synthetic.main.result_episode.view.episode_holder | ||||
| import kotlinx.android.synthetic.main.result_episode.view.episode_text | ||||
| import kotlinx.android.synthetic.main.result_episode_large.view.* | ||||
| import java.util.* | ||||
| 
 | ||||
| const val ACTION_PLAY_EPISODE_IN_PLAYER = 1 | ||||
| const val ACTION_PLAY_EPISODE_IN_VLC_PLAYER = 2 | ||||
|  | @ -49,12 +49,43 @@ class EpisodeAdapter( | |||
|     private val downloadClickCallback: (DownloadClickEvent) -> Unit, | ||||
| ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| 
 | ||||
|     private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet() | ||||
|     private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? { | ||||
|         return Collections.unmodifiableSet(mBoundViewHolders) | ||||
|     } | ||||
| 
 | ||||
|     fun killAdapter() { | ||||
|         getAllBoundViewHolders()?.forEach { view -> | ||||
|             view?.downloadButton?.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewRecycled(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.downloadButton.dispose() | ||||
|             mBoundViewHolders.remove(holder); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { | ||||
|         if (holder is DownloadButtonViewHolder) { | ||||
|             holder.reattachDownloadButton() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @LayoutRes | ||||
|     private var layout: Int = 0 | ||||
|     fun updateLayout() { | ||||
|         layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2f) // If over half has posters then use the large layout | ||||
|             R.layout.result_episode_large | ||||
|         else R.layout.result_episode | ||||
|         layout = | ||||
|             if (cardList.filter { it.poster != null }.size >= cardList.size / 2f) // If over half has posters then use the large layout | ||||
|                 R.layout.result_episode_large | ||||
|             else R.layout.result_episode | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|  | @ -62,7 +93,7 @@ class EpisodeAdapter( | |||
|             R.layout.result_episode_large | ||||
|         else R.layout.result_episode*/ | ||||
| 
 | ||||
|         return CardViewHolder( | ||||
|         return EpisodeCardViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(layout, parent, false), | ||||
|             hasDownloadSupport, | ||||
|             clickCallback, | ||||
|  | @ -72,8 +103,9 @@ class EpisodeAdapter( | |||
| 
 | ||||
|     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||||
|         when (holder) { | ||||
|             is CardViewHolder -> { | ||||
|             is EpisodeCardViewHolder -> { | ||||
|                 holder.bind(cardList[position]) | ||||
|                 mBoundViewHolders.add(holder) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -82,26 +114,31 @@ class EpisodeAdapter( | |||
|         return cardList.size | ||||
|     } | ||||
| 
 | ||||
|     class CardViewHolder | ||||
|     class EpisodeCardViewHolder | ||||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val hasDownloadSupport: Boolean, | ||||
|         val hasDownloadSupport: Boolean, | ||||
|         private val clickCallback: (EpisodeClickEvent) -> Unit, | ||||
|         private val downloadClickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|     ) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { | ||||
|         override var downloadButton = EasyDownloadButton() | ||||
| 
 | ||||
|         private val episodeText: TextView = itemView.episode_text | ||||
|         private val episodeRating: TextView? = itemView.episode_rating | ||||
|         private val episodeDescript: TextView? = itemView.episode_descript | ||||
|         private val episodeProgress: ContentLoadingProgressBar? = itemView.episode_progress | ||||
|         private val episodePoster: ImageView? = itemView.episode_poster | ||||
| 
 | ||||
|         private val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded | ||||
|         private val episodeDownloadImage: ImageView = itemView.result_episode_download | ||||
|         val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded | ||||
|         val episodeDownloadImage: ImageView = itemView.result_episode_download | ||||
| 
 | ||||
|         private val episodeHolder = itemView.episode_holder | ||||
| 
 | ||||
|         var localCard: ResultEpisode? = null | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun bind(card: ResultEpisode) { | ||||
|             localCard = card | ||||
|             val name = if (card.name == null) "Episode ${card.episode}" else "${card.episode}. ${card.name}" | ||||
|             episodeText.text = name | ||||
| 
 | ||||
|  | @ -148,11 +185,15 @@ class EpisodeAdapter( | |||
| 
 | ||||
|             episodeDownloadImage.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE | ||||
|             episodeDownloadBar.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE | ||||
|         } | ||||
| 
 | ||||
|             if (hasDownloadSupport) { | ||||
|         override fun reattachDownloadButton() { | ||||
|             downloadButton.dispose() | ||||
|             val card = localCard | ||||
|             if (hasDownloadSupport && card != null) { | ||||
|                 val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(itemView.context, card.id) | ||||
| 
 | ||||
|                 DownloadButtonSetup.setUpButton( | ||||
|                 downloadButton.setUpButton( | ||||
|                     downloadInfo?.fileLength, downloadInfo?.totalBytes, episodeDownloadBar, episodeDownloadImage, null, | ||||
|                     VideoDownloadHelper.DownloadEpisodeCached( | ||||
|                         card.name, card.poster, card.episode, card.season, card.id, 0, card.rating, card.descript | ||||
|  |  | |||
|  | @ -50,8 +50,9 @@ import com.lagradost.cloudstream3.mvvm.Resource | |||
| import com.lagradost.cloudstream3.mvvm.observe | ||||
| import com.lagradost.cloudstream3.ui.WatchType | ||||
| import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD | ||||
| import com.lagradost.cloudstream3.ui.download.EasyDownloadButton | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.setUpMaterialButton | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerData | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
|  | @ -70,7 +71,6 @@ import java.util.* | |||
| import kotlin.collections.ArrayList | ||||
| import kotlin.collections.HashMap | ||||
| 
 | ||||
| 
 | ||||
| const val MAX_SYNO_LENGH = 300 | ||||
| 
 | ||||
| data class ResultEpisode( | ||||
|  | @ -156,6 +156,7 @@ class ResultFragment : Fragment() { | |||
|     private var currentHeaderName: String? = null | ||||
|     private var currentType: TvType? = null | ||||
|     private var currentEpisodes: List<ResultEpisode>? = null | ||||
|     var downloadButton : EasyDownloadButton? = null | ||||
| 
 | ||||
|     override fun onCreateView( | ||||
|         inflater: LayoutInflater, | ||||
|  | @ -167,8 +168,15 @@ class ResultFragment : Fragment() { | |||
|         return inflater.inflate(R.layout.fragment_result, container, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroyView() { | ||||
|         (result_episodes?.adapter as EpisodeAdapter?)?.killAdapter() | ||||
|         super.onDestroyView() | ||||
|     } | ||||
| 
 | ||||
|     override fun onDestroy() { | ||||
|         //requireActivity().viewModelStore.clear() // REMEMBER THE CLEAR | ||||
|         downloadButton?.dispose() | ||||
| 
 | ||||
|         super.onDestroy() | ||||
|         activity?.let { | ||||
|             it.window?.navigationBarColor = | ||||
|  | @ -873,8 +881,9 @@ class ResultFragment : Fragment() { | |||
|                                 val localId = d.getId() | ||||
|                                 val file = | ||||
|                                     VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), localId) | ||||
| 
 | ||||
|                                 setUpMaterialButton( | ||||
|                                 downloadButton?.dispose() | ||||
|                                 downloadButton = EasyDownloadButton() | ||||
|                                 downloadButton?.setUpMaterialButton( | ||||
|                                     file?.fileLength, | ||||
|                                     file?.totalBytes, | ||||
|                                     result_movie_progress_downloaded, | ||||
|  |  | |||
|  | @ -131,8 +131,10 @@ class SearchFragment : Fragment() { | |||
|             when (it) { | ||||
|                 is Resource.Success -> { | ||||
|                     it.value.let { data -> | ||||
|                         (cardSpace?.adapter as SearchAdapter?)?.cardList = data | ||||
|                         cardSpace?.adapter?.notifyDataSetChanged() | ||||
|                         if(data != null) { | ||||
|                             (cardSpace?.adapter as SearchAdapter?)?.cardList = ArrayList( data.filterNotNull()) | ||||
|                             cardSpace?.adapter?.notifyDataSetChanged() | ||||
|                         } | ||||
|                     } | ||||
|                     searchExitIcon.alpha = 1f | ||||
|                     search_loading_bar.alpha = 0f | ||||
|  |  | |||
|  | @ -0,0 +1,12 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| interface IDisposable { | ||||
|     fun dispose() | ||||
| } | ||||
| 
 | ||||
| object IDisposableHelper { | ||||
|     fun <T : IDisposable> using(disposeObject: T, work: (T) -> Unit) { | ||||
|         work.invoke(disposeObject) | ||||
|         disposeObject.dispose() | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue