forked from recloudstream/cloudstream
download stuff
This commit is contained in:
parent
062d7feff9
commit
57828527aa
11 changed files with 281 additions and 65 deletions
|
@ -50,18 +50,22 @@ object UIHelper {
|
||||||
val Float.toDp: Float get() = (this / Resources.getSystem().displayMetrics.density)
|
val Float.toDp: Float get() = (this / Resources.getSystem().displayMetrics.density)
|
||||||
|
|
||||||
fun Activity.checkWrite(): Boolean {
|
fun Activity.checkWrite(): Boolean {
|
||||||
return (ContextCompat.checkSelfPermission(this,
|
return (ContextCompat.checkSelfPermission(
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
this,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
== PackageManager.PERMISSION_GRANTED)
|
== PackageManager.PERMISSION_GRANTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.requestRW() {
|
fun Activity.requestRW() {
|
||||||
ActivityCompat.requestPermissions(this,
|
ActivityCompat.requestPermissions(
|
||||||
|
this,
|
||||||
arrayOf(
|
arrayOf(
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
),
|
),
|
||||||
1337)
|
1337
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
|
@ -141,6 +145,7 @@ object UIHelper {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var currentAudioFocusRequest: AudioFocusRequest? = null
|
private var currentAudioFocusRequest: AudioFocusRequest? = null
|
||||||
private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null
|
private var currentAudioFocusChangeListener: AudioManager.OnAudioFocusChangeListener? = null
|
||||||
var onAudioFocusEvent = Event<Boolean>()
|
var onAudioFocusEvent = Event<Boolean>()
|
||||||
|
@ -258,6 +263,7 @@ object UIHelper {
|
||||||
)
|
)
|
||||||
// window.addFlags(View.KEEP_SCREEN_ON)
|
// window.addFlags(View.KEEP_SCREEN_ON)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun FragmentActivity.popCurrentPage() {
|
fun FragmentActivity.popCurrentPage() {
|
||||||
val currentFragment = supportFragmentManager.fragments.lastOrNull {
|
val currentFragment = supportFragmentManager.fragments.lastOrNull {
|
||||||
it.isVisible
|
it.isVisible
|
||||||
|
@ -363,10 +369,11 @@ object UIHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**id, icon, stringRes */
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
inline fun View.popupMenu(
|
fun View.popupMenu(
|
||||||
items: List<Triple<Int, Int, Int>>,
|
items: List<Triple<Int, Int, Int>>,
|
||||||
noinline onMenuItemClick: MenuItem.() -> Unit,
|
onMenuItemClick: MenuItem.() -> Unit,
|
||||||
): PopupMenu {
|
): PopupMenu {
|
||||||
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
||||||
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
||||||
|
@ -386,9 +393,11 @@ object UIHelper {
|
||||||
return popup
|
return popup
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun View.popupMenuNoIcons(
|
/**id, stringRes */
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
fun View.popupMenuNoIcons(
|
||||||
items: List<Pair<Int, Int>>,
|
items: List<Pair<Int, Int>>,
|
||||||
noinline onMenuItemClick: MenuItem.() -> Unit,
|
onMenuItemClick: MenuItem.() -> Unit,
|
||||||
): PopupMenu {
|
): PopupMenu {
|
||||||
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
||||||
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
||||||
|
@ -408,15 +417,17 @@ object UIHelper {
|
||||||
return popup
|
return popup
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun View.popupMenuNoIconsAndNoStringres(
|
/**id, string */
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
fun View.popupMenuNoIconsAndNoStringres(
|
||||||
items: List<Pair<Int, String>>,
|
items: List<Pair<Int, String>>,
|
||||||
noinline onMenuItemClick: MenuItem.() -> Unit,
|
onMenuItemClick: MenuItem.() -> Unit,
|
||||||
): PopupMenu {
|
): PopupMenu {
|
||||||
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
|
||||||
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
|
||||||
|
|
||||||
items.forEach { (id, stringRes) ->
|
items.forEach { (id, string) ->
|
||||||
popup.menu.add(0, id, 0, stringRes)
|
popup.menu.add(0, id, 0, string)
|
||||||
}
|
}
|
||||||
|
|
||||||
(popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true)
|
(popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true)
|
||||||
|
|
|
@ -1,19 +1,34 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.animation.DecelerateInterpolator
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
|
||||||
|
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getDownloadState
|
||||||
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
data class VisualDownloadChildCached(
|
data class VisualDownloadChildCached(
|
||||||
val currentBytes: Long,
|
val currentBytes: Long,
|
||||||
val totalBytes: Long,
|
val totalBytes: Long,
|
||||||
|
@ -56,6 +71,8 @@ class DownloadChildAdapter(
|
||||||
private val extraInfo: TextView = itemView.download_child_episode_text_extra
|
private val extraInfo: TextView = itemView.download_child_episode_text_extra
|
||||||
private val holder: CardView = itemView.download_child_episode_holder
|
private val holder: CardView = itemView.download_child_episode_holder
|
||||||
private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress
|
private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress
|
||||||
|
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
|
||||||
|
private val downloadImage: ImageView = itemView.download_child_episode_download
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: VisualDownloadChildCached) {
|
fun bind(card: VisualDownloadChildCached) {
|
||||||
|
@ -73,13 +90,91 @@ class DownloadChildAdapter(
|
||||||
|
|
||||||
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
|
title.text = d.name ?: "Episode ${d.episode}" //TODO FIX
|
||||||
val totalMbString = "%.1f".format(card.totalBytes / 1000000f)
|
val totalMbString = "%.1f".format(card.totalBytes / 1000000f)
|
||||||
val currentMbString = "%.1f".format(card.currentBytes / 1000000f)
|
|
||||||
|
|
||||||
extraInfo.text =
|
var lastState: VideoDownloadManager.DownloadType? = null
|
||||||
|
var currentBytes: Long = card.currentBytes
|
||||||
|
|
||||||
|
fun changeDownloadImage(state: VideoDownloadManager.DownloadType) {
|
||||||
|
runOnMainThread {
|
||||||
|
val img = when (state) {
|
||||||
|
VideoDownloadManager.DownloadType.IsPaused -> R.drawable.ic_baseline_play_arrow_24
|
||||||
|
VideoDownloadManager.DownloadType.IsDownloading -> R.drawable.netflix_pause
|
||||||
|
else -> R.drawable.ic_baseline_delete_outline_24
|
||||||
|
}
|
||||||
|
downloadImage?.setImageResource(img)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fixDownloadedBytes(setCurrentBytes: Long, animate : Boolean) {
|
||||||
|
currentBytes = setCurrentBytes
|
||||||
|
runOnMainThread {
|
||||||
|
val currentMbString = "%.1f".format(currentBytes / 1000000f)
|
||||||
|
|
||||||
|
extraInfo?.text =
|
||||||
"${currentMbString}MB / ${totalMbString}MB"
|
"${currentMbString}MB / ${totalMbString}MB"
|
||||||
|
|
||||||
|
progressBarDownload?.let { bar ->
|
||||||
|
bar.max = (card.totalBytes / 1000).toInt()
|
||||||
|
|
||||||
|
if(animate) {
|
||||||
|
val animation: ObjectAnimator = ObjectAnimator.ofInt(
|
||||||
|
bar,
|
||||||
|
"progress",
|
||||||
|
bar.progress,
|
||||||
|
(currentBytes / 1000).toInt()
|
||||||
|
)
|
||||||
|
animation.duration = 500
|
||||||
|
animation.setAutoCancel(true)
|
||||||
|
animation.interpolator = DecelerateInterpolator()
|
||||||
|
animation.start()
|
||||||
|
} else {
|
||||||
|
bar.progress = (currentBytes / 1000).toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixDownloadedBytes(card.currentBytes, false)
|
||||||
|
changeDownloadImage(getDownloadState(card.data.id))
|
||||||
|
|
||||||
|
VideoDownloadManager.downloadProgressEvent += { downloadData ->
|
||||||
|
if (card.data.id == downloadData.first) {
|
||||||
|
fixDownloadedBytes(downloadData.second, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoDownloadManager.downloadStatusEvent += { downloadData ->
|
||||||
|
if (card.data.id == downloadData.first) {
|
||||||
|
if (lastState != downloadData.second) { // TO PREVENT WASTING UI TIME
|
||||||
|
lastState = downloadData.second
|
||||||
|
changeDownloadImage(downloadData.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
clickCallback.invoke(DownloadClickEvent(0, d))
|
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBarDownload.setOnClickListener {
|
||||||
|
val list = arrayListOf(
|
||||||
|
Pair(DOWNLOAD_ACTION_DELETE_FILE, R.string.popup_delete_file),
|
||||||
|
)
|
||||||
|
|
||||||
|
// DON'T RESUME A DOWNLOADED FILE
|
||||||
|
if (lastState != VideoDownloadManager.DownloadType.IsDone && (currentBytes * 100 / card.totalBytes < 98)) {
|
||||||
|
list.add(
|
||||||
|
if (lastState == VideoDownloadManager.DownloadType.IsDownloading)
|
||||||
|
Pair(DOWNLOAD_ACTION_PAUSE_DOWNLOAD, R.string.popup_pause_download)
|
||||||
|
else
|
||||||
|
Pair(DOWNLOAD_ACTION_RESUME_DOWNLOAD, R.string.popup_resume_download)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
it.popupMenuNoIcons(
|
||||||
|
list
|
||||||
|
) {
|
||||||
|
clickCallback.invoke(DownloadClickEvent(itemId, d))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,8 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||||
import com.lagradost.cloudstream3.ui.player.UriData
|
import com.lagradost.cloudstream3.ui.player.UriData
|
||||||
import com.lagradost.cloudstream3.ui.result.getRealPosition
|
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
|
@ -84,7 +82,33 @@ class DownloadChildFragment : Fragment() {
|
||||||
DownloadChildAdapter(
|
DownloadChildAdapter(
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
) { click ->
|
) { click ->
|
||||||
if (click.action == 0) { // TODO PLAY
|
val id = click.data.id
|
||||||
|
when (click.action) {
|
||||||
|
DOWNLOAD_ACTION_DELETE_FILE -> {
|
||||||
|
context?.let { ctx ->
|
||||||
|
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
||||||
|
}
|
||||||
|
updateList(folder)
|
||||||
|
}
|
||||||
|
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
||||||
|
VideoDownloadManager.downloadEvent.invoke(
|
||||||
|
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
||||||
|
)
|
||||||
|
updateList(folder)
|
||||||
|
}
|
||||||
|
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
||||||
|
context?.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 -> {
|
||||||
val info =
|
val info =
|
||||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id)
|
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), click.data.id)
|
||||||
?: return@DownloadChildAdapter
|
?: return@DownloadChildAdapter
|
||||||
|
@ -112,6 +136,7 @@ class DownloadChildFragment : Fragment() {
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
download_child_list.adapter = adapter
|
download_child_list.adapter = adapter
|
||||||
download_child_list.layoutManager = GridLayoutManager(context, 1)
|
download_child_list.layoutManager = GridLayoutManager(context, 1)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -11,4 +13,10 @@ object Coroutines {
|
||||||
work()
|
work()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun runOnMainThread(work: (() -> Unit)) {
|
||||||
|
val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
mainHandler.post {
|
||||||
|
work()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -166,6 +166,16 @@ object VideoDownloadManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Will return IsDone if not found or error */
|
||||||
|
fun getDownloadState(id : Int) : DownloadType {
|
||||||
|
return try {
|
||||||
|
downloadStatus[id] ?: DownloadType.IsDone
|
||||||
|
} catch (e : Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
DownloadType.IsDone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val cachedBitmaps = hashMapOf<String, Bitmap>()
|
private val cachedBitmaps = hashMapOf<String, Bitmap>()
|
||||||
private fun Context.getImageBitmapFromUrl(url: String): Bitmap? {
|
private fun Context.getImageBitmapFromUrl(url: String): Bitmap? {
|
||||||
if (cachedBitmaps.containsKey(url)) {
|
if (cachedBitmaps.containsKey(url)) {
|
||||||
|
@ -532,6 +542,7 @@ object VideoDownloadManager {
|
||||||
try {
|
try {
|
||||||
downloadStatus[ep.id] = type
|
downloadStatus[ep.id] = type
|
||||||
downloadStatusEvent.invoke(Pair(ep.id, type))
|
downloadStatusEvent.invoke(Pair(ep.id, type))
|
||||||
|
downloadProgressEvent.invoke(Pair(ep.id, bytesDownloaded))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// IDK MIGHT ERROR
|
// IDK MIGHT ERROR
|
||||||
}
|
}
|
||||||
|
@ -584,7 +595,7 @@ object VideoDownloadManager {
|
||||||
count = connectionInputStream.read(buffer)
|
count = connectionInputStream.read(buffer)
|
||||||
if (count < 0) break
|
if (count < 0) break
|
||||||
bytesDownloaded += count
|
bytesDownloaded += count
|
||||||
downloadProgressEvent.invoke(Pair(id, bytesDownloaded))
|
// downloadProgressEvent.invoke(Pair(id, bytesDownloaded)) // Updates too much for any UI to keep up with
|
||||||
while (isPaused) {
|
while (isPaused) {
|
||||||
sleep(100)
|
sleep(100)
|
||||||
if (isStopped) {
|
if (isStopped) {
|
||||||
|
@ -621,6 +632,7 @@ object VideoDownloadManager {
|
||||||
deleteFile()
|
deleteFile()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
downloadProgressEvent.invoke(Pair(id, bytesDownloaded))
|
||||||
isDone = true
|
isDone = true
|
||||||
updateNotification()
|
updateNotification()
|
||||||
SUCCESS_DOWNLOAD_DONE
|
SUCCESS_DOWNLOAD_DONE
|
||||||
|
@ -741,6 +753,10 @@ object VideoDownloadManager {
|
||||||
downloadQueue.addLast(pkg)
|
downloadQueue.addLast(pkg)
|
||||||
downloadCheck(context)
|
downloadCheck(context)
|
||||||
if (setKey) saveQueue(context)
|
if (setKey) saveQueue(context)
|
||||||
|
} else {
|
||||||
|
downloadEvent.invoke(
|
||||||
|
Pair(pkg.item.ep.id, DownloadActionType.Resume)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
app/src/main/res/drawable/circle_shape.xml
Normal file
11
app/src/main/res/drawable/circle_shape.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="ring"
|
||||||
|
android:innerRadiusRatio="2.5"
|
||||||
|
android:thickness="2dp"
|
||||||
|
android:useLevel="false">
|
||||||
|
|
||||||
|
<solid android:color="#CCC" />
|
||||||
|
|
||||||
|
</shape>
|
18
app/src/main/res/drawable/circular_progress_bar.xml
Normal file
18
app/src/main/res/drawable/circular_progress_bar.xml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:fromDegrees="270"
|
||||||
|
android:toDegrees="270">
|
||||||
|
<shape
|
||||||
|
android:innerRadiusRatio="2.5"
|
||||||
|
android:shape="ring"
|
||||||
|
android:thickness="2dp"
|
||||||
|
android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->
|
||||||
|
|
||||||
|
<gradient
|
||||||
|
android:angle="0"
|
||||||
|
android:endColor="?attr/colorPrimary"
|
||||||
|
android:startColor="?attr/colorPrimary"
|
||||||
|
android:type="sweep"
|
||||||
|
android:useLevel="false" />
|
||||||
|
</shape>
|
||||||
|
</rotate>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8,9h8v10L8,19L8,9zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/>
|
||||||
|
</vector>
|
|
@ -25,6 +25,7 @@
|
||||||
</androidx.core.widget.ContentLoadingProgressBar>
|
</androidx.core.widget.ContentLoadingProgressBar>
|
||||||
<GridLayout android:layout_width="match_parent" android:layout_height="match_parent">
|
<GridLayout android:layout_width="match_parent" android:layout_height="match_parent">
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:visibility="gone"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
|
@ -56,18 +57,39 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
</TextView>
|
</TextView>
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
<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/download_child_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
|
<ImageView
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:padding="2dp"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:id="@+id/download_child_episode_download"
|
android:id="@+id/download_child_episode_download"
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:layout_gravity="center_vertical|end"
|
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||||
android:src="@drawable/netflix_download"
|
|
||||||
android:contentDescription="@string/download_descript"/>
|
android:contentDescription="@string/download_descript"/>
|
||||||
|
</FrameLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -101,7 +101,7 @@
|
||||||
|
|
||||||
</ImageView>-->
|
</ImageView>-->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="Dub"
|
android:text="@string/app_dubbed_text"
|
||||||
android:id="@+id/text_is_dub"
|
android:id="@+id/text_is_dub"
|
||||||
android:textColor="@color/textColor"
|
android:textColor="@color/textColor"
|
||||||
android:paddingRight="10dp"
|
android:paddingRight="10dp"
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
</TextView>
|
</TextView>
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_is_sub"
|
android:id="@+id/text_is_sub"
|
||||||
android:text="Sub"
|
android:text="@string/app_subbed_text"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="end"
|
||||||
android:textColor="@color/textColor"
|
android:textColor="@color/textColor"
|
||||||
android:paddingRight="10dp"
|
android:paddingRight="10dp"
|
||||||
|
|
|
@ -42,4 +42,9 @@
|
||||||
<string name="error_loading_links">Error Loading Links</string>
|
<string name="error_loading_links">Error Loading Links</string>
|
||||||
<string name="download_storage_text">Internal Storage</string>
|
<string name="download_storage_text">Internal Storage</string>
|
||||||
<string name="options">Options</string>
|
<string name="options">Options</string>
|
||||||
|
<string name="app_dubbed_text">Dub</string>
|
||||||
|
<string name="app_subbed_text">Sub</string>
|
||||||
|
<string name="popup_delete_file">Delete File</string>
|
||||||
|
<string name="popup_resume_download">Resume Download</string>
|
||||||
|
<string name="popup_pause_download">Pause Download</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue