mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	download stuff
This commit is contained in:
		
							parent
							
								
									472a9d678a
								
							
						
					
					
						commit
						3606d1ec05
					
				
					 8 changed files with 321 additions and 93 deletions
				
			
		|  | @ -0,0 +1,195 @@ | |||
| package com.lagradost.cloudstream3.ui.download | ||||
| 
 | ||||
| import android.animation.ObjectAnimator | ||||
| import android.annotation.SuppressLint | ||||
| import android.app.Activity | ||||
| import android.view.View | ||||
| import android.view.animation.DecelerateInterpolator | ||||
| import android.widget.ImageView | ||||
| import android.widget.TextView | ||||
| import androidx.core.widget.ContentLoadingProgressBar | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| 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 { | ||||
|     fun handleDownloadClick(activity: Activity?, headerName: String?, click: DownloadClickEvent) { | ||||
|         val id = click.data.id | ||||
|         when (click.action) { | ||||
|             DOWNLOAD_ACTION_DELETE_FILE -> { | ||||
|                 activity?.let { ctx -> | ||||
|                     VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id) | ||||
|                 } | ||||
|             } | ||||
|             DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> { | ||||
|                 VideoDownloadManager.downloadEvent.invoke( | ||||
|                     Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause) | ||||
|                 ) | ||||
|             } | ||||
|             DOWNLOAD_ACTION_RESUME_DOWNLOAD -> { | ||||
|                 activity?.let { ctx -> | ||||
|                     val pkg = VideoDownloadManager.getDownloadResumePackage(ctx, id) | ||||
|                     if (pkg != null) { | ||||
|                         VideoDownloadManager.downloadFromResume(ctx, pkg) | ||||
|                     } else { | ||||
|                         VideoDownloadManager.downloadEvent.invoke( | ||||
|                             Pair(click.data.id, VideoDownloadManager.DownloadActionType.Resume) | ||||
|                         ) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             DOWNLOAD_ACTION_PLAY_FILE -> { | ||||
|                 activity?.let { act -> | ||||
|                     val info = | ||||
|                         VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(act, click.data.id) | ||||
|                             ?: return | ||||
| 
 | ||||
|                     (act as FragmentActivity).supportFragmentManager.beginTransaction() | ||||
|                         .setCustomAnimations( | ||||
|                             R.anim.enter_anim, | ||||
|                             R.anim.exit_anim, | ||||
|                             R.anim.pop_enter, | ||||
|                             R.anim.pop_exit | ||||
|                         ) | ||||
|                         .add( | ||||
|                             R.id.homeRoot, | ||||
|                             PlayerFragment.newInstance( | ||||
|                                 UriData( | ||||
|                                     info.path.toString(), | ||||
|                                     click.data.id, | ||||
|                                     headerName ?: "null", | ||||
|                                     click.data.episode, | ||||
|                                     click.data.season | ||||
|                                 ), | ||||
|                                 act.getViewPos(click.data.id)?.position ?: 0 | ||||
|                             ) | ||||
|                         ) | ||||
|                         .commit() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fun setUpButton( | ||||
|         setupCurrentBytes: Long?, | ||||
|         setupTotalBytes: Long?, | ||||
|         progressBar: ContentLoadingProgressBar, | ||||
|         downloadImage: ImageView, | ||||
|         textView: TextView?, | ||||
|         data: VideoDownloadHelper.DownloadEpisodeCached, | ||||
|         clickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) { | ||||
|         var lastState: VideoDownloadManager.DownloadType? = null | ||||
|         var currentBytes = setupCurrentBytes ?: 0 | ||||
|         var totalBytes = setupTotalBytes ?: 0 | ||||
|         var needImageUpdate = false | ||||
| 
 | ||||
|         fun changeDownloadImage(state: VideoDownloadManager.DownloadType) { | ||||
|             Coroutines.runOnMainThread { | ||||
|                 lastState = state | ||||
|                 if (currentBytes <= 0) needImageUpdate = true | ||||
|                 val img = if (currentBytes > 0) when (state) { | ||||
|                     VideoDownloadManager.DownloadType.IsPaused -> R.drawable.ic_baseline_play_arrow_24 | ||||
|                     VideoDownloadManager.DownloadType.IsDownloading -> R.drawable.netflix_pause | ||||
|                     else -> R.drawable.ic_baseline_delete_outline_24 | ||||
|                 } else R.drawable.netflix_download | ||||
|                 downloadImage?.setImageResource(img) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @SuppressLint("SetTextI18n") | ||||
|         fun fixDownloadedBytes(setCurrentBytes: Long, setTotalBytes: Long, animate: Boolean) { | ||||
|             Coroutines.runOnMainThread { | ||||
|                 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)) | ||||
| 
 | ||||
|         VideoDownloadManager.downloadProgressEvent += { downloadData -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (downloadData.second != currentBytes || downloadData.third != totalBytes) { // TO PREVENT WASTING UI TIME | ||||
|                     fixDownloadedBytes(downloadData.second, downloadData.third, true) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         VideoDownloadManager.downloadStatusEvent += { downloadData -> | ||||
|             if (data.id == downloadData.first) { | ||||
|                 if (lastState != downloadData.second || needImageUpdate) { // TO PREVENT WASTING UI TIME | ||||
|                     changeDownloadImage(downloadData.second) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         downloadImage.setOnClickListener { | ||||
|             if (currentBytes <= 0) { | ||||
|                 clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) | ||||
|             } else { | ||||
|                 val list = arrayListOf( | ||||
|                     Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file), | ||||
|                 ) | ||||
| 
 | ||||
|                 // DON'T RESUME A DOWNLOADED FILE | ||||
|                 if (lastState != VideoDownloadManager.DownloadType.IsDone && ((currentBytes * 100 / 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)) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -28,6 +28,7 @@ const val DOWNLOAD_ACTION_PLAY_FILE = 0 | |||
| const val DOWNLOAD_ACTION_DELETE_FILE = 1 | ||||
| const val DOWNLOAD_ACTION_RESUME_DOWNLOAD = 2 | ||||
| const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3 | ||||
| const val DOWNLOAD_ACTION_DOWNLOAD = 4 | ||||
| 
 | ||||
| data class VisualDownloadChildCached( | ||||
|     val currentBytes: Long, | ||||
|  | @ -89,6 +90,16 @@ class DownloadChildAdapter( | |||
|             } | ||||
| 
 | ||||
|             title.text = d.name ?: "Episode ${d.episode}" //TODO FIX | ||||
|             DownloadButtonSetup.setUpButton( | ||||
|                 card.currentBytes, | ||||
|                 card.totalBytes, | ||||
|                 progressBarDownload, | ||||
|                 downloadImage, | ||||
|                 extraInfo, | ||||
|                 card.data, | ||||
|                 clickCallback | ||||
|             ) | ||||
|             /* | ||||
|             val totalMbString = "%.1f".format(card.totalBytes / 1000000f) | ||||
| 
 | ||||
|             var lastState: VideoDownloadManager.DownloadType? = null | ||||
|  | @ -175,7 +186,7 @@ class DownloadChildAdapter( | |||
|                 ) { | ||||
|                     clickCallback.invoke(DownloadClickEvent(itemId, d)) | ||||
|                 } | ||||
|             } | ||||
|             }*/ | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ 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.ui.download.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||
| import com.lagradost.cloudstream3.ui.player.UriData | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.main | ||||
|  | @ -35,63 +36,6 @@ class DownloadChildFragment : Fragment() { | |||
|                     putString("name", headerName) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         fun handleDownloadClick(activity: Activity?, headerName: String?, click: DownloadClickEvent) { | ||||
|             val id = click.data.id | ||||
|             when (click.action) { | ||||
|                 DOWNLOAD_ACTION_DELETE_FILE -> { | ||||
|                     activity?.let { ctx -> | ||||
|                         VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id) | ||||
|                     } | ||||
|                 } | ||||
|                 DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> { | ||||
|                     VideoDownloadManager.downloadEvent.invoke( | ||||
|                         Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause) | ||||
|                     ) | ||||
|                 } | ||||
|                 DOWNLOAD_ACTION_RESUME_DOWNLOAD -> { | ||||
|                     activity?.let { ctx -> | ||||
|                         val pkg = VideoDownloadManager.getDownloadResumePackage(ctx, id) | ||||
|                         if (pkg != null) { | ||||
|                             VideoDownloadManager.downloadFromResume(ctx, pkg) | ||||
|                         } else { | ||||
|                             VideoDownloadManager.downloadEvent.invoke( | ||||
|                                 Pair(click.data.id, VideoDownloadManager.DownloadActionType.Resume) | ||||
|                             ) | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 DOWNLOAD_ACTION_PLAY_FILE -> { | ||||
|                     activity?.let { act -> | ||||
|                         val info = | ||||
|                             VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(act, click.data.id) | ||||
|                                 ?: return | ||||
| 
 | ||||
|                         (act as FragmentActivity).supportFragmentManager.beginTransaction() | ||||
|                             .setCustomAnimations( | ||||
|                                 R.anim.enter_anim, | ||||
|                                 R.anim.exit_anim, | ||||
|                                 R.anim.pop_enter, | ||||
|                                 R.anim.pop_exit | ||||
|                             ) | ||||
|                             .add( | ||||
|                                 R.id.homeRoot, | ||||
|                                 PlayerFragment.newInstance( | ||||
|                                     UriData( | ||||
|                                         info.path.toString(), | ||||
|                                         click.data.id, | ||||
|                                         headerName ?: "null", | ||||
|                                         click.data.episode, | ||||
|                                         click.data.season | ||||
|                                     ), | ||||
|                                     act.getViewPos(click.data.id)?.position ?: 0 | ||||
|                                 ) | ||||
|                             ) | ||||
|                             .commit() | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|  |  | |||
|  | @ -12,6 +12,11 @@ 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.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.DownloadClickEvent | ||||
| import com.lagradost.cloudstream3.utils.VideoDownloadHelper | ||||
| 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.* | ||||
|  | @ -37,8 +42,9 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode) | |||
| 
 | ||||
| class EpisodeAdapter( | ||||
|     var cardList: List<ResultEpisode>, | ||||
|     val hasDownloadSupport : Boolean, | ||||
|     private val hasDownloadSupport: Boolean, | ||||
|     private val clickCallback: (EpisodeClickEvent) -> Unit, | ||||
|     private val downloadClickCallback: (DownloadClickEvent) -> Unit, | ||||
| ) : | ||||
|     RecyclerView.Adapter<RecyclerView.ViewHolder>() { | ||||
|     @LayoutRes | ||||
|  | @ -57,7 +63,8 @@ class EpisodeAdapter( | |||
|         return CardViewHolder( | ||||
|             LayoutInflater.from(parent.context).inflate(layout, parent, false), | ||||
|             hasDownloadSupport, | ||||
|             clickCallback | ||||
|             clickCallback, | ||||
|             downloadClickCallback | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  | @ -76,15 +83,18 @@ class EpisodeAdapter( | |||
|     class CardViewHolder | ||||
|     constructor( | ||||
|         itemView: View, | ||||
|         private val hasDownloadSupport : Boolean, | ||||
|         private val hasDownloadSupport: Boolean, | ||||
|         private val clickCallback: (EpisodeClickEvent) -> Unit, | ||||
|         private val downloadClickCallback: (DownloadClickEvent) -> Unit, | ||||
|     ) : RecyclerView.ViewHolder(itemView) { | ||||
|         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 episodeDownload: ImageView? = itemView.episode_download | ||||
| 
 | ||||
|         private val episodeDownloadBar: ContentLoadingProgressBar = itemView.result_episode_progress_downloaded | ||||
|         private val episodeDownloadImage: ImageView = itemView.result_episode_download | ||||
| 
 | ||||
|         private val episodeHolder = itemView.episode_holder | ||||
| 
 | ||||
|  | @ -134,11 +144,23 @@ class EpisodeAdapter( | |||
|                 return@setOnLongClickListener true | ||||
|             } | ||||
| 
 | ||||
|             episodeDownload?.visibility = if(hasDownloadSupport) View.VISIBLE else View.GONE | ||||
| 
 | ||||
|             episodeDownload?.setOnClickListener { | ||||
|             if(hasDownloadSupport) { | ||||
|                 DownloadButtonSetup.setUpButton( | ||||
|                     null, null, episodeDownloadBar, episodeDownloadImage, null, | ||||
|                     VideoDownloadHelper.DownloadEpisodeCached( | ||||
|                         card.name, card.poster, card.episode, card.season, card.id, 0, card.rating, card.descript | ||||
|                     ) | ||||
|                 ) { | ||||
|                     if(it.action == DOWNLOAD_ACTION_DOWNLOAD) { | ||||
|                         clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card)) | ||||
|                     } else { | ||||
|                         downloadClickCallback.invoke(it) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             episodeDownloadImage.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE | ||||
|             episodeDownloadBar.visibility = if (hasDownloadSupport) View.VISIBLE else View.GONE | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -47,6 +47,8 @@ import com.lagradost.cloudstream3.UIHelper.requestRW | |||
| 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.DownloadButtonSetup.handleDownloadClick | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerData | ||||
| import com.lagradost.cloudstream3.ui.player.PlayerFragment | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
|  | @ -625,9 +627,13 @@ class ResultFragment : Fragment() { | |||
|             EpisodeAdapter( | ||||
|                 ArrayList(), | ||||
|                 api.hasDownloadSupport, | ||||
|             ) { episodeClick -> | ||||
|                 { episodeClick -> | ||||
|                     handleAction(episodeClick) | ||||
|                 }, | ||||
|                 { downloadClickEvent -> | ||||
|                     handleDownloadClick(activity, currentHeaderName, downloadClickEvent) | ||||
|                 } | ||||
|             ) | ||||
| 
 | ||||
|         result_episodes.adapter = adapter | ||||
|         result_episodes.layoutManager = GridLayoutManager(context, 1) | ||||
|  |  | |||
|  | @ -144,7 +144,7 @@ object VideoDownloadManager { | |||
|     val downloadStatus = HashMap<Int, DownloadType>() | ||||
|     val downloadStatusEvent = Event<Pair<Int, DownloadType>>() | ||||
|     val downloadEvent = Event<Pair<Int, DownloadActionType>>() | ||||
|     val downloadProgressEvent = Event<Pair<Int, Long>>() | ||||
|     val downloadProgressEvent = Event<Triple<Int, Long, Long>>() | ||||
|     val downloadQueue = LinkedList<DownloadResumePackage>() | ||||
| 
 | ||||
|     private var hasCreatedNotChanel = false | ||||
|  | @ -542,7 +542,7 @@ object VideoDownloadManager { | |||
|             try { | ||||
|                 downloadStatus[ep.id] = type | ||||
|                 downloadStatusEvent.invoke(Pair(ep.id, type)) | ||||
|                 downloadProgressEvent.invoke(Pair(ep.id, bytesDownloaded)) | ||||
|                 downloadProgressEvent.invoke(Triple(ep.id, bytesDownloaded, bytesTotal)) | ||||
|             } catch (e: Exception) { | ||||
|                 // IDK MIGHT ERROR | ||||
|             } | ||||
|  | @ -626,13 +626,15 @@ object VideoDownloadManager { | |||
|         // RETURN MESSAGE | ||||
|         return when { | ||||
|             isFailed -> { | ||||
|                 downloadProgressEvent.invoke(Triple(id, 0, 0)) | ||||
|                 ERROR_CONNECTION_ERROR | ||||
|             } | ||||
|             isStopped -> { | ||||
|                 downloadProgressEvent.invoke(Triple(id, 0, 0)) | ||||
|                 deleteFile() | ||||
|             } | ||||
|             else -> { | ||||
|                 downloadProgressEvent.invoke(Pair(id, bytesDownloaded)) | ||||
|                 downloadProgressEvent.invoke(Triple(id, bytesDownloaded, bytesTotal)) | ||||
|                 isDone = true | ||||
|                 updateNotification() | ||||
|                 SUCCESS_DOWNLOAD_DONE | ||||
|  | @ -715,6 +717,8 @@ object VideoDownloadManager { | |||
| 
 | ||||
|     private fun deleteFile(context: Context, id: Int): Boolean { | ||||
|         downloadEvent.invoke(Pair(id, DownloadActionType.Stop)) | ||||
|         downloadProgressEvent.invoke(Triple(id, 0, 0)) | ||||
|         downloadStatusEvent.invoke(Pair(id, DownloadType.IsStopped)) | ||||
|         val info = context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return false | ||||
| 
 | ||||
|         if (isScopedStorage()) { | ||||
|  |  | |||
|  | @ -61,16 +61,38 @@ | |||
|                 android:textColor="@color/textColor" android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent"> | ||||
|         </TextView> | ||||
|          | ||||
|         <FrameLayout | ||||
|                 android:layout_gravity="end" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="match_parent"> | ||||
|             <androidx.core.widget.ContentLoadingProgressBar | ||||
|                     android:layout_marginEnd="10dp" | ||||
|                     android:layout_marginStart="10dp" | ||||
|                     android:layout_width="40dp" | ||||
|                     android:layout_height="40dp" | ||||
|                     android:id="@+id/result_episode_progress_downloaded" | ||||
|                     android:indeterminate="false" | ||||
|                     android:progressDrawable="@drawable/circular_progress_bar" | ||||
|                     android:background="@drawable/circle_shape" | ||||
|                     style="?android:attr/progressBarStyleHorizontal" | ||||
|                     android:max="100" | ||||
|                     android:layout_margin="5dp" | ||||
|                     android:layout_gravity="end|center_vertical" | ||||
|                     android:progress="0" | ||||
|                     android:visibility="visible" | ||||
|             /> | ||||
|             <ImageView | ||||
|                     android:visibility="visible" | ||||
|                     android:layout_marginEnd="10dp" | ||||
|                     android:layout_marginStart="10dp" | ||||
|                     android:layout_height="match_parent" | ||||
|                     android:padding="2dp" | ||||
|                     android:layout_width="30dp" | ||||
|                 android:id="@+id/episode_download" | ||||
|                     android:id="@+id/result_episode_download" | ||||
|                     android:background="?selectableItemBackgroundBorderless" | ||||
|                 android:layout_gravity="center_vertical|end" | ||||
|                 android:src="@drawable/netflix_download" | ||||
|                     android:src="@drawable/ic_baseline_play_arrow_24" | ||||
|                     android:contentDescription="@string/download_descript"/> | ||||
|         </FrameLayout> | ||||
|     </GridLayout> | ||||
| </androidx.cardview.widget.CardView> | ||||
|  | @ -76,16 +76,40 @@ | |||
|                         android:layout_height="wrap_content"> | ||||
|                 </TextView> | ||||
|             </LinearLayout> | ||||
|             <FrameLayout | ||||
|                     android:layout_marginStart="-50dp" | ||||
|                     android:layout_gravity="end" | ||||
|                     android:layout_width="wrap_content" | ||||
|                     android:layout_height="match_parent"> | ||||
|                 <androidx.core.widget.ContentLoadingProgressBar | ||||
|                         android:layout_marginEnd="10dp" | ||||
|                         android:layout_marginStart="10dp" | ||||
|                         android:layout_width="40dp" | ||||
|                         android:layout_height="40dp" | ||||
|                         android:id="@+id/result_episode_progress_downloaded" | ||||
|                         android:indeterminate="false" | ||||
|                         android:progressDrawable="@drawable/circular_progress_bar" | ||||
|                         android:background="@drawable/circle_shape" | ||||
|                         style="?android:attr/progressBarStyleHorizontal" | ||||
|                         android:max="100" | ||||
|                         android:layout_margin="5dp" | ||||
|                         android:layout_gravity="end|center_vertical" | ||||
|                         android:progress="0" | ||||
|                         android:visibility="visible" | ||||
|                 /> | ||||
|                 <ImageView | ||||
|                         android:visibility="visible" | ||||
|                     android:layout_marginStart="-40dp" | ||||
|                         android:layout_marginEnd="10dp" | ||||
|                         android:layout_marginStart="10dp" | ||||
|                         android:layout_height="match_parent" | ||||
|                         android:padding="2dp" | ||||
|                         android:layout_width="30dp" | ||||
|                     android:id="@+id/episode_download" | ||||
|                         android:id="@+id/result_episode_download" | ||||
|                         android:background="?selectableItemBackgroundBorderless" | ||||
|                     android:layout_gravity="center_vertical|end" | ||||
|                     android:src="@drawable/netflix_download" | ||||
|                         android:src="@drawable/ic_baseline_play_arrow_24" | ||||
|                         android:contentDescription="@string/download_descript"/> | ||||
|             </FrameLayout> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
|         <TextView | ||||
|                 android:paddingTop="10dp" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue