mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	download headers
This commit is contained in:
		
							parent
							
								
									8a519176ca
								
							
						
					
					
						commit
						ddd722f19e
					
				
					 12 changed files with 295 additions and 62 deletions
				
			
		|  | @ -113,6 +113,7 @@ class MainActivity : AppCompatActivity() { | |||
|                 val dur: Long = | ||||
|                     data.getLongExtra(VLC_EXTRA_DURATION_OUT, -1) //Last position in media when player exited | ||||
|                 val id = getKey<Int>(VLC_LAST_ID_KEY) | ||||
|                 println("SET KEY $id at $pos / $dur") | ||||
|                 if (dur > 0 && pos > 0) { | ||||
|                     setViewPos(id, pos, dur) | ||||
|                 } | ||||
|  |  | |||
|  | @ -1,31 +1,81 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.annotation.SuppressLint | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.TextView | ||||
| import android.widget.LinearLayout | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.lifecycle.Observer | ||||
| import androidx.lifecycle.ViewModelProvider | ||||
| 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.mvvm.observe | ||||
| import kotlinx.android.synthetic.main.fragment_downloads.* | ||||
| import kotlinx.android.synthetic.main.fragment_result.* | ||||
| 
 | ||||
| 
 | ||||
| class DownloadFragment : Fragment() { | ||||
| 
 | ||||
|     private lateinit var notificationsViewModel: DownloadViewModel | ||||
|     private lateinit var downloadsViewModel: DownloadViewModel | ||||
| 
 | ||||
|     private fun getBytesAsText(bytes: Long): String { | ||||
|         return "%.1f".format(bytes / 1000000000f) | ||||
|     } | ||||
| 
 | ||||
|     private fun View.setLayoutWidth(weight: Long) { | ||||
|         val param = LinearLayout.LayoutParams( | ||||
|             0, | ||||
|             LinearLayout.LayoutParams.MATCH_PARENT, | ||||
|             maxOf((weight / 1000000000f), 0.1f) // 100mb | ||||
|         ) | ||||
|         this.layoutParams = param | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("SetTextI18n") | ||||
|     override fun onCreateView( | ||||
|         inflater: LayoutInflater, | ||||
|         container: ViewGroup?, | ||||
|         savedInstanceState: Bundle? | ||||
|     ): View? { | ||||
|         notificationsViewModel = | ||||
|         downloadsViewModel = | ||||
|             ViewModelProvider(this).get(DownloadViewModel::class.java) | ||||
|         val root = inflater.inflate(R.layout.fragment_notifications, container, false) | ||||
|         val textView: TextView = root.findViewById(R.id.text_notifications) | ||||
|         notificationsViewModel.text.observe(viewLifecycleOwner, Observer { | ||||
|             textView.text = it | ||||
|         }) | ||||
|         return root | ||||
|         observe(downloadsViewModel.noDownloadsText) { | ||||
|             text_no_downloads.text = it | ||||
|         } | ||||
|         observe(downloadsViewModel.headerCards) { | ||||
|             (download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).cardList = it | ||||
|             (download_list?.adapter as DownloadHeaderAdapter? ?: return@observe).notifyDataSetChanged() | ||||
|         } | ||||
|         observe(downloadsViewModel.availableBytes) { | ||||
|             download_free_txt?.text = "Free • ${getBytesAsText(it)}GB" | ||||
|             download_free?.setLayoutWidth(it) | ||||
|         } | ||||
|         observe(downloadsViewModel.usedBytes) { | ||||
|             download_used_txt?.text = "Used • ${getBytesAsText(it)}GB" | ||||
|             download_used?.setLayoutWidth(it) | ||||
|         } | ||||
|         observe(downloadsViewModel.downloadBytes) { | ||||
|             download_app_txt?.text = "App • ${getBytesAsText(it)}GB" | ||||
|             download_app?.setLayoutWidth(it) | ||||
|         } | ||||
|         return inflater.inflate(R.layout.fragment_downloads, container, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|         val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> = | ||||
|             DownloadHeaderAdapter( | ||||
|                 ArrayList(), | ||||
|             ) { click -> | ||||
| 
 | ||||
|             } | ||||
|         download_list.adapter = adapter | ||||
|         download_list.layoutManager = GridLayoutManager(context, 1) | ||||
|         downloadsViewModel.updateList(requireContext()) | ||||
| 
 | ||||
|         activity?.fixPaddingStatusbar(download_root) | ||||
|     } | ||||
| } | ||||
|  | @ -1,13 +1,95 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.os.Environment | ||||
| import android.os.StatFs | ||||
| import androidx.lifecycle.LiveData | ||||
| import androidx.lifecycle.MutableLiveData | ||||
| import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE | ||||
| import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE | ||||
| 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.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.launch | ||||
| import kotlinx.coroutines.withContext | ||||
| 
 | ||||
| class DownloadViewModel : ViewModel() { | ||||
| 
 | ||||
|     private val _text = MutableLiveData<String>().apply { | ||||
|         value = "This is notifications Fragment" | ||||
|     private val _noDownloadsText = MutableLiveData<String>().apply { | ||||
|         value = "" | ||||
|     } | ||||
|     val noDownloadsText: LiveData<String> = _noDownloadsText | ||||
| 
 | ||||
|     private val _headerCards = | ||||
|         MutableLiveData<List<VisualDownloadHeaderCached>>().apply { listOf<VisualDownloadHeaderCached>() } | ||||
|     val headerCards: LiveData<List<VisualDownloadHeaderCached>> = _headerCards | ||||
| 
 | ||||
|     private val _usedBytes = MutableLiveData<Long>() | ||||
|     private val _availableBytes = MutableLiveData<Long>() | ||||
|     private val _downloadBytes = MutableLiveData<Long>() | ||||
| 
 | ||||
|     val usedBytes: LiveData<Long> = _usedBytes | ||||
|     val availableBytes: LiveData<Long> = _availableBytes | ||||
|     val downloadBytes: LiveData<Long> = _downloadBytes | ||||
| 
 | ||||
|     fun updateList(context: Context) = viewModelScope.launch { | ||||
|         val children = withContext(Dispatchers.IO) { | ||||
|             val headers = context.getKeys(DOWNLOAD_EPISODE_CACHE) | ||||
|             headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadEpisodeCached>(it) } | ||||
|         } | ||||
| 
 | ||||
|         // parentId : bytes | ||||
|         val bytesUsedByChild = HashMap<Int, Long>() | ||||
|         // parentId : downloadsCount | ||||
|         val totalDownloads = HashMap<Int, Int>() | ||||
| 
 | ||||
|         // Gets all children downloads | ||||
|         withContext(Dispatchers.IO) { | ||||
|             for (c in children) { | ||||
|                 val childFile = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, c.id) | ||||
|                 val len = childFile?.totalBytes ?: continue | ||||
|                 if (bytesUsedByChild.containsKey(c.parentId)) { | ||||
|                     bytesUsedByChild[c.parentId] = bytesUsedByChild[c.parentId]?.plus(len) ?: len | ||||
|                 } else { | ||||
|                     bytesUsedByChild[c.parentId] = len | ||||
|                 } | ||||
| 
 | ||||
|                 if (totalDownloads.containsKey(c.parentId)) { | ||||
|                     totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1 | ||||
|                 } else { | ||||
|                     totalDownloads[c.parentId] = 1 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val cached = withContext(Dispatchers.IO) { | ||||
|             val headers = context.getKeys(DOWNLOAD_HEADER_CACHE) | ||||
|             headers.mapNotNull { context.getKey<VideoDownloadHelper.DownloadHeaderCached>(it) } | ||||
|         } | ||||
| 
 | ||||
|         val visual = withContext(Dispatchers.IO) { | ||||
|             cached.mapNotNull { // TODO FIX | ||||
|                 val downloads = totalDownloads[it.id] ?: 0 | ||||
|                 val bytes = bytesUsedByChild[it.id] ?: 0 | ||||
|                 if(bytes <= 0 || downloads <= 0) return@mapNotNull null | ||||
|                 VisualDownloadHeaderCached(0, downloads, bytes, it) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         val stat = StatFs(Environment.getExternalStorageDirectory().path) | ||||
| 
 | ||||
|         val localBytesAvailable = stat.availableBytes//stat.blockSizeLong * stat.blockCountLong | ||||
|         val localTotalBytes = stat.blockSizeLong * stat.blockCountLong | ||||
|         val localDownloadedBytes = visual.sumOf { it.totalBytes } | ||||
| 
 | ||||
|         _usedBytes.postValue(localTotalBytes - localBytesAvailable - localDownloadedBytes) | ||||
|         _availableBytes.postValue(localBytesAvailable) | ||||
|         _downloadBytes.postValue(localDownloadedBytes) | ||||
| 
 | ||||
|         _headerCards.postValue(visual) | ||||
|     } | ||||
|     val text: LiveData<String> = _text | ||||
| } | ||||
|  | @ -352,7 +352,7 @@ class ResultFragment : Fragment() { | |||
|                     episodeClick.data.index, | ||||
|                     eps, | ||||
|                     sortUrls(currentLinks ?: return), | ||||
|                     currentSubs ?: return, | ||||
|                     currentSubs ?: ArrayList(), | ||||
|                     startTime = episodeClick.data.getRealPosition(), | ||||
|                     startIndex = startIndex | ||||
|                 ) | ||||
|  | @ -548,7 +548,7 @@ class ResultFragment : Fragment() { | |||
|                     vlcIntent.putExtra("position", position) | ||||
| 
 | ||||
|                     vlcIntent.component = VLC_COMPONENT | ||||
|                     requireContext().setKey(VLC_LAST_ID_KEY, currentId) | ||||
|                     requireContext().setKey(VLC_LAST_ID_KEY, episodeClick.data.id) | ||||
|                     activity?.startActivityForResult(vlcIntent, VLC_REQUEST_CODE) | ||||
|                 } | ||||
| 
 | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ class SearchFragment : Fragment() { | |||
|         allApi.providersActive = requireActivity().getApiSettings() | ||||
| 
 | ||||
|         //searchViewModel.search("iron man") | ||||
|         (activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") | ||||
|         //(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") | ||||
| /* | ||||
|         (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction() | ||||
|             .setCustomAnimations(R.anim.enter_anim, | ||||
|  |  | |||
|  | @ -53,11 +53,12 @@ | |||
|                     android:layout_height="wrap_content"> | ||||
|             </TextView> | ||||
|         </LinearLayout> | ||||
|         <!-- | ||||
|                 android:background="?selectableItemBackgroundBorderless"--> | ||||
|         <ImageView | ||||
|                 android:layout_marginStart="-40dp" | ||||
|                 android:layout_height="match_parent" | ||||
|                 android:layout_width="30dp" | ||||
|                 android:background="?selectableItemBackgroundBorderless" | ||||
|                 android:layout_gravity="center_vertical|end" | ||||
|                 android:src="@drawable/ic_baseline_keyboard_arrow_right_24" | ||||
|                 android:contentDescription="@string/download_descript"/> | ||||
|  |  | |||
							
								
								
									
										118
									
								
								app/src/main/res/layout/fragment_downloads.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								app/src/main/res/layout/fragment_downloads.xml
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,118 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout | ||||
|         android:id="@+id/download_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"> | ||||
|     <LinearLayout | ||||
|             android:layout_margin="10dp" | ||||
|             android:orientation="vertical" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
|         <TextView | ||||
|                 android:layout_marginBottom="5dp" | ||||
|                 android:text="@string/download_storage_text" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content"> | ||||
|         </TextView> | ||||
|         <LinearLayout | ||||
|                 android:layout_marginBottom="5dp" | ||||
|                 android:layout_width="fill_parent" | ||||
|                 android:layout_height="12dp" | ||||
|                 android:orientation="horizontal"> | ||||
|             <View | ||||
|                     android:layout_weight="0.5" | ||||
|                     android:id="@+id/download_used" | ||||
|                     android:background="@color/usedStorageColor" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="match_parent"/> | ||||
|             <View | ||||
|                     android:id="@+id/download_app" | ||||
|                     android:layout_weight="0.10" | ||||
|                     android:background="?attr/colorPrimary" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="match_parent"/> | ||||
|             <View | ||||
|                     android:id="@+id/download_free" | ||||
|                     android:layout_weight="0.10" | ||||
|                     android:background="@color/freeStorageColor" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="match_parent"/> | ||||
|         </LinearLayout> | ||||
|         <LinearLayout | ||||
|                 android:orientation="horizontal" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content"> | ||||
|             <View | ||||
|                     android:layout_marginEnd="5dp" | ||||
|                     android:layout_marginTop="5dp" | ||||
|                     android:layout_marginBottom="5dp" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     android:background="@color/usedStorageColor" | ||||
|                     android:layout_width="10dp" | ||||
|                     android:layout_height="10dp"/> | ||||
|             <TextView | ||||
|                     android:id="@+id/download_used_txt" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     tools:text="Used • 30.58GB" | ||||
|                     android:textSize="12sp" | ||||
|                     android:textColor="?attr/textColor" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content"/> | ||||
| 
 | ||||
|             <View | ||||
|                     android:layout_margin="5dp" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     android:background="?attr/colorPrimary" | ||||
|                     android:layout_width="10dp" | ||||
|                     android:layout_height="10dp"/> | ||||
|             <TextView | ||||
|                     android:id="@+id/download_app_txt" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     tools:text="App • 30.58GB" | ||||
|                     android:textSize="12sp" | ||||
|                     android:textColor="?attr/textColor" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content"/> | ||||
|             <View | ||||
|                     android:layout_margin="5dp" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     android:background="@color/freeStorageColor" | ||||
|                     android:layout_width="10dp" | ||||
|                     android:layout_height="10dp"/> | ||||
|             <TextView | ||||
|                     android:id="@+id/download_free_txt" | ||||
|                     android:textSize="12sp" | ||||
|                     android:layout_gravity="center_vertical" | ||||
|                     tools:text="Free • 30.58GB" | ||||
|                     android:textColor="?attr/textColor" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="wrap_content"/> | ||||
|         </LinearLayout> | ||||
|     </LinearLayout> | ||||
| 
 | ||||
|     <androidx.recyclerview.widget.RecyclerView | ||||
|             android:layout_margin="10dp" | ||||
|             android:id="@+id/download_list" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content"> | ||||
| 
 | ||||
|     </androidx.recyclerview.widget.RecyclerView> | ||||
|     <TextView | ||||
|             android:id="@+id/text_no_downloads" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="8dp" | ||||
|             android:layout_marginTop="8dp" | ||||
|             android:layout_marginEnd="8dp" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="20sp" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             app:layout_constraintBottom_toBottomOf="parent"/> | ||||
| </LinearLayout> | ||||
|  | @ -1,23 +0,0 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.constraintlayout.widget.ConstraintLayout | ||||
|         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"> | ||||
| 
 | ||||
|     <TextView | ||||
|             android:id="@+id/text_notifications" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_marginStart="8dp" | ||||
|             android:layout_marginTop="8dp" | ||||
|             android:layout_marginEnd="8dp" | ||||
|             android:textAlignment="center" | ||||
|             android:textSize="20sp" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|             app:layout_constraintTop_toTopOf="parent" | ||||
|             app:layout_constraintBottom_toBottomOf="parent"/> | ||||
| </androidx.constraintlayout.widget.ConstraintLayout> | ||||
|  | @ -13,27 +13,27 @@ | |||
|         android:layout_marginBottom="5dp" | ||||
| > | ||||
|     <!-- IDK BUT THIS DOES NOT SEAM LIKE A GOOD WAY OF DOING IT --> | ||||
|     <!--<LinearLayout | ||||
|             android:layout_width="fill_parent" | ||||
|             android:layout_height="fill_parent" | ||||
|             android:orientation="horizontal"> | ||||
|         <View | ||||
|                 android:layout_weight="0.5" | ||||
|                 android:id="@+id/episode_view_procentage" | ||||
|                 android:alpha="0.2" | ||||
|                 android:background="@color/colorPrimary" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="match_parent"> | ||||
|         </View> | ||||
|         <View | ||||
|                 android:id="@+id/episode_view_procentage_off" | ||||
|                 android:layout_weight="0.10" | ||||
|                 android:alpha="0" | ||||
|                 android:background="@color/transparent" | ||||
|                 android:layout_width="0dp" | ||||
|                 android:layout_height="match_parent"> | ||||
|         </View> | ||||
|     </LinearLayout>--> | ||||
|         <!--<LinearLayout | ||||
|                 android:layout_width="fill_parent" | ||||
|                 android:layout_height="fill_parent" | ||||
|                 android:orientation="horizontal"> | ||||
|             <View | ||||
|                     android:layout_weight="0.5" | ||||
|                     android:id="@+id/episode_view_procentage" | ||||
|                     android:alpha="0.2" | ||||
|                     android:background="@color/colorPrimary" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </View> | ||||
|             <View | ||||
|                     android:id="@+id/episode_view_procentage_off" | ||||
|                     android:layout_weight="0.10" | ||||
|                     android:alpha="0" | ||||
|                     android:background="@color/transparent" | ||||
|                     android:layout_width="0dp" | ||||
|                     android:layout_height="match_parent"> | ||||
|             </View> | ||||
|         </LinearLayout>--> | ||||
|     <androidx.core.widget.ContentLoadingProgressBar | ||||
|             android:layout_marginBottom="-1.5dp" | ||||
|             android:id="@+id/episode_progress" | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ | |||
|             android:id="@+id/navigation_notifications" | ||||
|             android:name="com.lagradost.cloudstream3.ui.download.DownloadFragment" | ||||
|             android:label="@string/title_downloads" | ||||
|             tools:layout="@layout/fragment_notifications"/> | ||||
|             tools:layout="@layout/fragment_downloads"/> | ||||
|     <fragment | ||||
|             android:id="@+id/navigation_settings" | ||||
|             android:layout_height="match_parent" | ||||
|  |  | |||
|  | @ -38,4 +38,7 @@ | |||
|     <color name="videoColorPrimary">@color/colorPrimary</color> <!--0e09df 617EFF 3d50fa--> | ||||
| 
 | ||||
|     <color name="iconColor">#9ba0a6</color> | ||||
| 
 | ||||
|     <color name="usedStorageColor">#FFF</color> | ||||
|     <color name="freeStorageColor">#676767</color> | ||||
| </resources> | ||||
|  | @ -40,4 +40,5 @@ | |||
|     <string name="need_storage">Allow to download episodes</string> | ||||
|     <string name="download_descript">Download</string> | ||||
|     <string name="error_loading_links">Error Loading Links</string> | ||||
|     <string name="download_storage_text">Internal Storage</string> | ||||
| </resources> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue