mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	download child
This commit is contained in:
		
							parent
							
								
									ddd722f19e
								
							
						
					
					
						commit
						3bf76a9563
					
				
					 11 changed files with 292 additions and 9 deletions
				
			
		|  | @ -0,0 +1,86 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.annotation.SuppressLint | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| 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.utils.DataStoreHelper.fixVisual | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import kotlinx.android.synthetic.main.download_child_episode.view.* | ||||
| 
 | ||||
| data class VisualDownloadChildCached( | ||||
|     val currentBytes: Long, | ||||
|     val totalBytes: Long, | ||||
|     val data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
| ) | ||||
| 
 | ||||
| data class DownloadClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadEpisodeCached) | ||||
| 
 | ||||
| class DownloadChildAdapter( | ||||
|     var cardList: List<VisualDownloadChildCached>, | ||||
|     private val clickCallback: (DownloadClickEvent) -> Unit, | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
| 
 | ||||
|     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { | ||||
|         return DownloadChildViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(R.layout.download_child_episode, parent, false), | ||||
|             clickCallback | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { | ||||
|         when (holder) { | ||||
|             is DownloadChildViewHolder -> { | ||||
|                 holder.bind(cardList[position]) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun getItemCount(): Int { | ||||
|         return cardList.size | ||||
|     } | ||||
| 
 | ||||
|     class DownloadChildViewHolder | ||||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|         private val title: TextView = itemView.download_child_episode_text | ||||
|         private val extraInfo: TextView = itemView.download_child_episode_text_extra | ||||
|         private val holder: CardView = itemView.download_child_episode_holder | ||||
|         private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun bind(card: VisualDownloadChildCached) { | ||||
|             val d = card.data | ||||
| 
 | ||||
|             val posDur = itemView.context.getViewPos(d.id) | ||||
|             if (posDur != null) { | ||||
|                 val visualPos = posDur.fixVisual() | ||||
|                 progressBar.max = (visualPos.duration / 1000).toInt() | ||||
|                 progressBar.progress = (visualPos.position / 1000).toInt() | ||||
|                 progressBar.visibility = View.VISIBLE | ||||
|             } else { | ||||
|                 progressBar.visibility = View.GONE | ||||
|             } | ||||
| 
 | ||||
|             title.text = d.name ?: "Episode ${d.episode}" //TODO FIX | ||||
|             val totalMbString = "%.1f".format(card.totalBytes / 1000000f) | ||||
|             val currentMbString = "%.1f".format(card.currentBytes / 1000000f) | ||||
| 
 | ||||
|             extraInfo.text = | ||||
|                 "${currentMbString}MB / ${totalMbString}MB" | ||||
| 
 | ||||
|             holder.setOnClickListener { | ||||
|                 clickCallback.invoke(DownloadClickEvent(0, d)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,87 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.recyclerview.widget.GridLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKeys | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadManager | ||||
| import kotlinx.android.synthetic.main.fragment_child_downloads.* | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.withContext | ||||
| 
 | ||||
| class DownloadChildFragment : Fragment() { | ||||
|     companion object { | ||||
|         fun newInstance(headerName: String, folder: String) = | ||||
|             DownloadChildFragment().apply { | ||||
|                 arguments = Bundle().apply { | ||||
|                     putString("folder", folder) | ||||
|                     putString("name", headerName) | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_child_downloads, container, false) | ||||
|     } | ||||
| 
 | ||||
|     private fun updateList(folder: String) = main { | ||||
|         val data = withContext(Dispatchers.IO) { context?.getKeys(folder) } | ||||
|         if (data == null) { | ||||
|             activity?.onBackPressed() // TODO FIX | ||||
|             return@main | ||||
|         } | ||||
|         val eps = withContext(Dispatchers.IO) { | ||||
|             data.mapNotNull { key -> | ||||
|                 context?.getKey<VideoDownloadHelper.DownloadEpisodeCached>(key) | ||||
|             }.mapNotNull { | ||||
|                 val info = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), it.id) | ||||
|                     ?: return@mapNotNull null | ||||
|                 VisualDownloadChildCached(info.fileLength, info.totalBytes, it) | ||||
|             } | ||||
|         } | ||||
|         if (eps.isEmpty()) { | ||||
|             activity?.onBackPressed() | ||||
|             return@main | ||||
|         } | ||||
| 
 | ||||
|         (download_child_list?.adapter as DownloadChildAdapter? ?: return@main).cardList = eps | ||||
|         download_child_list?.adapter?.notifyDataSetChanged() | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         val folder = arguments?.getString("folder") | ||||
|         val name = arguments?.getString("name") | ||||
|         if (folder == null) { | ||||
|             activity?.onBackPressed() // TODO FIX | ||||
|             return | ||||
|         } | ||||
|         context?.fixPaddingStatusbar(download_child_root) | ||||
| 
 | ||||
| 
 | ||||
|         val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = | ||||
|             DownloadChildAdapter( | ||||
|                 ArrayList(), | ||||
|             ) { click -> | ||||
|                 if (click.action == 0) { // TODO PLAY | ||||
|                     val info = | ||||
|                         VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id) | ||||
|                             ?: return@DownloadChildAdapter | ||||
|                 } | ||||
|             } | ||||
|         download_child_list.adapter = adapter | ||||
|         download_child_list.layoutManager = GridLayoutManager(context, 1) | ||||
| 
 | ||||
|         updateList(folder) | ||||
|     } | ||||
| } | ||||
|  | @ -12,7 +12,11 @@ import androidx.recyclerview.widget.GridLayoutManager | |||
| import androidx.recyclerview.widget.RecyclerView | ||||
| 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.result.ResultFragment | ||||
| import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getFolderName | ||||
| import kotlinx.android.synthetic.main.fragment_downloads.* | ||||
| import kotlinx.android.synthetic.main.fragment_result.* | ||||
| 
 | ||||
|  | @ -70,7 +74,16 @@ class DownloadFragment : Fragment() { | |||
|             DownloadHeaderAdapter( | ||||
|                 ArrayList(), | ||||
|             ) { click -> | ||||
| 
 | ||||
|                 if(click.data.type.isMovieType()) { | ||||
|                     //TODO MOVIE | ||||
|                 } | ||||
|                 else { | ||||
|                     val folder = getFolderName(DOWNLOAD_EPISODE_CACHE, click.data.id.toString()) | ||||
|                     activity?.supportFragmentManager?.beginTransaction() | ||||
|                         ?.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit) | ||||
|                         ?.add(R.id.homeRoot, DownloadChildFragment.newInstance(click.data.name, folder)) | ||||
|                         ?.commit() | ||||
|                 } | ||||
|             } | ||||
|         download_list.adapter = adapter | ||||
|         download_list.layoutManager = GridLayoutManager(context, 1) | ||||
|  |  | |||
|  | @ -23,7 +23,6 @@ data class VisualDownloadHeaderCached( | |||
| ) | ||||
| 
 | ||||
| data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached) | ||||
| data class DownloadClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadEpisodeCached) | ||||
| 
 | ||||
| class DownloadHeaderAdapter( | ||||
|     var cardList: List<VisualDownloadHeaderCached>, | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ import com.lagradost.cloudstream3.ui.player.PlayerFragment | |||
| import com.lagradost.cloudstream3.utils.* | ||||
| import com.lagradost.cloudstream3.utils.CastHelper.startCast | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getFolderName | ||||
| import com.lagradost.cloudstream3.utils.DataStore.setKey | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos | ||||
| 
 | ||||
|  | @ -396,7 +397,7 @@ class ResultFragment : Fragment() { | |||
| 
 | ||||
|                     val epData = episodeClick.data | ||||
|                     ctx.setKey( | ||||
|                         DOWNLOAD_EPISODE_CACHE, | ||||
|                         getFolderName(DOWNLOAD_EPISODE_CACHE, (currentId ?: return@let).toString()), // 3 deep folder for faster acess | ||||
|                         epData.id.toString(), | ||||
|                         VideoDownloadHelper.DownloadEpisodeCached( | ||||
|                             epData.name, | ||||
|  |  | |||
|  | @ -9,9 +9,18 @@ const val VIDEO_POS_DUR = "video_pos_dur" | |||
| const val RESULT_WATCH_STATE = "result_watch_state" | ||||
| const val RESULT_SEASON = "result_season" | ||||
| 
 | ||||
| data class PosDur(val position: Long, val duration: Long) | ||||
| 
 | ||||
| object DataStoreHelper { | ||||
|     data class PosDur(val position: Long, val duration: Long) | ||||
|     fun PosDur.fixVisual(): PosDur { | ||||
|         if (duration <= 0) return PosDur(0, duration) | ||||
|         val percentage = position * 100 / duration | ||||
|         if (percentage <= 1) return PosDur(0, duration) | ||||
|         if (percentage <= 5) return PosDur(5 * duration / 100, duration) | ||||
|         if (percentage >= 95) return PosDur(duration, duration) | ||||
|         return this | ||||
|     } | ||||
| 
 | ||||
|     var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION | ||||
| 
 | ||||
|     fun Context.setViewPos(id: Int?, pos: Long, dur: Long) { | ||||
|  |  | |||
|  | @ -22,9 +22,6 @@ import com.lagradost.cloudstream3.R | |||
| import com.lagradost.cloudstream3.UIHelper.colorFromAttribute | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.services.RESTART_NONE | ||||
| import com.lagradost.cloudstream3.services.START_VALUE_KEY | ||||
| import com.lagradost.cloudstream3.services.VideoDownloadKeepAliveService | ||||
| import com.lagradost.cloudstream3.services.VideoDownloadService | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
| import com.lagradost.cloudstream3.utils.DataStore.getKey | ||||
|  |  | |||
							
								
								
									
										73
									
								
								app/src/main/res/layout/download_child_episode.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								app/src/main/res/layout/download_child_episode.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.cardview.widget.CardView | ||||
|         xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="50dp" | ||||
|         xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|         xmlns:tools="http://schemas.android.com/tools" | ||||
|         app:cardCornerRadius="@dimen/roundedImageRadius" | ||||
|         app:cardBackgroundColor="@color/transparent" | ||||
|         app:cardElevation="0dp" | ||||
|         android:id="@+id/download_child_episode_holder" | ||||
|         android:foreground="?android:attr/selectableItemBackgroundBorderless" | ||||
|         android:layout_marginBottom="5dp" | ||||
| > | ||||
|     <androidx.core.widget.ContentLoadingProgressBar | ||||
|             android:layout_marginBottom="-1.5dp" | ||||
|             android:id="@+id/download_child_episode_progress" | ||||
|             android:progressTint="@color/colorPrimary" | ||||
|             android:progressBackgroundTint="@color/colorPrimary" | ||||
|             style="@android:style/Widget.Material.ProgressBar.Horizontal" | ||||
|             android:layout_width="match_parent" | ||||
|             tools:progress="50" | ||||
|             android:layout_gravity="bottom" | ||||
|             android:layout_height="5dp"> | ||||
|     </androidx.core.widget.ContentLoadingProgressBar> | ||||
|     <GridLayout android:layout_width="match_parent" android:layout_height="match_parent"> | ||||
|         <ImageView | ||||
|                 android:layout_marginStart="10dp" | ||||
|                 android:layout_marginEnd="10dp" | ||||
|                 android:layout_gravity="center_vertical" | ||||
|                 android:id="@+id/download_child_episode_play" | ||||
|                 android:src="@drawable/ic_baseline_play_arrow_24" | ||||
|                 android:contentDescription="@string/episode_play_descript"/> | ||||
|         <LinearLayout | ||||
|                 android:layout_gravity="center_vertical" | ||||
|                 android:orientation="vertical" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_width="wrap_content" | ||||
|             > | ||||
|             <TextView | ||||
|                     android:id="@+id/download_child_episode_text" | ||||
|                     android:layout_marginStart="10dp" | ||||
|                     android:layout_marginEnd="10dp" | ||||
|                     android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="Episode 1" | ||||
|                     android:textColor="@color/textColor" android:layout_width="wrap_content" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </TextView> | ||||
|             <TextView | ||||
|                     android:id="@+id/download_child_episode_text_extra" | ||||
|                     android:layout_marginStart="10dp" | ||||
|                     android:layout_marginEnd="10dp" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     android:gravity="center_vertical" | ||||
|                     tools:text="128MB / 237MB" | ||||
|                     android:textColor="@color/grayTextColor" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </TextView> | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <ImageView | ||||
|                 android:visibility="gone" | ||||
|                 android:layout_marginEnd="10dp" | ||||
|                 android:layout_marginStart="10dp" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_width="30dp" | ||||
|                 android:id="@+id/download_child_episode_download" | ||||
|                 android:background="?selectableItemBackgroundBorderless" | ||||
|                 android:layout_gravity="center_vertical|end" | ||||
|                 android:src="@drawable/netflix_download" | ||||
|                 android:contentDescription="@string/download_descript"/> | ||||
|     </GridLayout> | ||||
| </androidx.cardview.widget.CardView> | ||||
|  | @ -17,7 +17,6 @@ | |||
|             android:layout_height="wrap_content"> | ||||
|         <!--app:cardCornerRadius="@dimen/roundedImageRadius"--> | ||||
|         <androidx.cardview.widget.CardView | ||||
| 
 | ||||
|                 android:layout_width="70dp" | ||||
|                 android:layout_height="104dp" | ||||
|         > | ||||
|  |  | |||
							
								
								
									
										19
									
								
								app/src/main/res/layout/fragment_child_downloads.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app/src/main/res/layout/fragment_child_downloads.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout | ||||
|         android:background="@color/bitDarkerGrayBackground" | ||||
|         android:id="@+id/download_child_root" | ||||
|         android:orientation="vertical" | ||||
|         xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|         xmlns:tools="http://schemas.android.com/tools" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         tools:context=".ui.download.DownloadFragment"> | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|             android:layout_margin="10dp" | ||||
|             tools:listitem="@layout/download_child_episode" | ||||
|             android:id="@+id/download_child_list" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
|     </androidx.recyclerview.widget.RecyclerView> | ||||
| </LinearLayout> | ||||
|  | @ -99,8 +99,8 @@ | |||
|             android:layout_margin="10dp" | ||||
|             android:id="@+id/download_list" | ||||
|             android:layout_width="match_parent" | ||||
|             tools:listitem="@layout/download_header_episode" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|     </androidx.recyclerview.widget.RecyclerView> | ||||
|     <TextView | ||||
|             android:id="@+id/text_no_downloads" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue