forked from recloudstream/cloudstream
Compare commits
7 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a1165344d3 | ||
|
fa399cd350 | ||
|
6a721941ac | ||
|
572aa6de3e | ||
|
45ea1a8d8e | ||
|
63e4e670c0 | ||
|
266a511cd7 |
28 changed files with 1278 additions and 954 deletions
|
@ -199,6 +199,9 @@ dependencies {
|
|||
|
||||
// Library/extensions searching with Levenshtein distance
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||
|
||||
// aria2c downloader
|
||||
implementation 'com.github.LagradOst:Aria2cButton:v0.0.6'
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
|
|
|
@ -17,6 +17,8 @@ import androidx.appcompat.widget.SearchView
|
|||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.gms.cast.framework.CastSession
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.ui.download.Aria2cHelper.removeMetadata
|
||||
import com.lagradost.cloudstream3.ui.download.Aria2cHelper.saveMetadata
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerEventType
|
||||
import com.lagradost.cloudstream3.ui.result.UiText
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateTv
|
||||
|
@ -25,8 +27,13 @@ import com.lagradost.cloudstream3.utils.UIHelper
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||
import com.lagradost.fetchbutton.aria2c.Aria2Settings
|
||||
import com.lagradost.fetchbutton.aria2c.Aria2Starter
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadListener
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import java.util.*
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
object CommonActivity {
|
||||
@MainThread
|
||||
|
@ -129,6 +136,43 @@ object CommonActivity {
|
|||
act.updateLocale()
|
||||
act.updateTv()
|
||||
NewPipe.init(DownloaderTestImpl.getInstance())
|
||||
|
||||
DownloadListener.mainListener = { (data, metadata) ->
|
||||
//TODO FIX
|
||||
DownloadListener.sessionGidToId[data.gid]?.let { id ->
|
||||
if (metadata.status == DownloadStatusTell.Removed
|
||||
|| metadata.status == DownloadStatusTell.Error
|
||||
|| metadata.status == DownloadStatusTell.Waiting
|
||||
|| metadata.status == null) {
|
||||
removeMetadata(id)
|
||||
} else {
|
||||
saveMetadata(id, metadata)
|
||||
}
|
||||
/*val mainpath = metadata.items[0].files[0].path
|
||||
AcraApplication.setKey(
|
||||
VideoDownloadManager.KEY_DOWNLOAD_INFO,
|
||||
id.toString(),
|
||||
VideoDownloadManager.DownloadedFileInfo(
|
||||
metadata.totalLength,
|
||||
relativePath ?: "",
|
||||
,
|
||||
basePath = basePath.second
|
||||
)
|
||||
)*/
|
||||
}
|
||||
}
|
||||
|
||||
thread {
|
||||
Aria2Starter.start(
|
||||
act,
|
||||
Aria2Settings(
|
||||
"1337", //UUID.randomUUID().toString()
|
||||
4337,
|
||||
act.filesDir.path + "/download", //"/storage/emulated/0/Download",//
|
||||
null//"${act.filesDir.path}/session"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Activity.enterPIPMode() {
|
||||
|
|
|
@ -10,10 +10,10 @@ import android.view.KeyEvent
|
|||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.navigation.NavController
|
||||
|
@ -107,6 +107,8 @@ const val VLC_EXTRA_POSITION_OUT = "extra_position"
|
|||
const val VLC_EXTRA_DURATION_OUT = "extra_duration"
|
||||
const val VLC_LAST_ID_KEY = "vlc_last_open_id"
|
||||
|
||||
const val DOWNLOAD_COUNT_KEY = "download_badge_count"
|
||||
|
||||
// Short name for requests client to make it nicer to use
|
||||
|
||||
var app = Requests(responseParser = object : ResponseParser {
|
||||
|
@ -150,7 +152,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
* @return true if the str has launched an app task (be it successful or not)
|
||||
* @param isWebview does not handle providers and opening download page if true. Can still add repos and login.
|
||||
* */
|
||||
fun handleAppIntentUrl(activity: FragmentActivity?, str: String?, isWebview: Boolean): Boolean =
|
||||
fun handleAppIntentUrl(
|
||||
activity: FragmentActivity?,
|
||||
str: String?,
|
||||
isWebview: Boolean
|
||||
): Boolean =
|
||||
with(activity) {
|
||||
if (str != null && this != null) {
|
||||
if (str.startsWith("https://cs.repo")) {
|
||||
|
@ -191,7 +197,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
val url = str.replaceFirst(appStringRepo, "https")
|
||||
loadRepository(url)
|
||||
return true
|
||||
} else if (!isWebview){
|
||||
} else if (!isWebview) {
|
||||
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
||||
this.navigate(R.id.navigation_downloads)
|
||||
return true
|
||||
|
@ -267,6 +273,25 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
}
|
||||
}
|
||||
|
||||
if (destination.id == R.id.navigation_download_child || destination.id == R.id.navigation_downloads) {
|
||||
setKey(DOWNLOAD_COUNT_KEY, 0)
|
||||
}
|
||||
|
||||
nav_view?.getOrCreateBadge(R.id.navigation_downloads)?.apply {
|
||||
val count = getKey(DOWNLOAD_COUNT_KEY) ?: 0
|
||||
if (count <= 0) {
|
||||
clearNumber()
|
||||
isVisible = false
|
||||
} else {
|
||||
this.backgroundColor =
|
||||
getResourceColor(R.attr.colorPrimary)
|
||||
this.badgeTextColor =
|
||||
getResourceColor(R.attr.colorOnPrimary)
|
||||
isVisible = true
|
||||
number = count
|
||||
}
|
||||
}
|
||||
|
||||
nav_view?.isVisible = isNavVisible && !landscape
|
||||
nav_rail_view?.isVisible = isNavVisible && landscape
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.lagradost.cloudstream3.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
||||
import com.lagradost.fetchbutton.aria2c.Metadata
|
||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
|
||||
class DownloadButton(context: Context, attributeSet: AttributeSet) :
|
||||
PieFetchButton(context, attributeSet) {
|
||||
|
||||
var progressText: TextView? = null
|
||||
var mainText: TextView? = null
|
||||
var bigButton: MaterialButton? = null
|
||||
|
||||
override fun onInflate() {
|
||||
overrideLayout = R.layout.download_button_layout
|
||||
super.onInflate()
|
||||
progressText = findViewById(R.id.result_movie_download_text_precentage)
|
||||
mainText = findViewById(R.id.result_movie_download_text)
|
||||
bigButton = findViewById(R.id.download_big_button)
|
||||
}
|
||||
|
||||
override fun setOnClickListener(l: OnClickListener?) {
|
||||
bigButton?.setOnClickListener(l)
|
||||
}
|
||||
|
||||
override fun setOnLongClickListener(l: OnLongClickListener?) {
|
||||
bigButton?.setOnLongClickListener(l)
|
||||
}
|
||||
|
||||
override fun setStatus(status: DownloadStatusTell?) {
|
||||
super.setStatus(status)
|
||||
val txt = when (status) {
|
||||
DownloadStatusTell.Paused -> R.string.download_paused
|
||||
DownloadStatusTell.Active -> R.string.downloading
|
||||
DownloadStatusTell.Complete -> R.string.downloaded
|
||||
else -> R.string.download
|
||||
}
|
||||
mainText?.setText(txt)
|
||||
}
|
||||
|
||||
override fun updateViewOnDownload(metadata: Metadata) {
|
||||
super.updateViewOnDownload(metadata)
|
||||
|
||||
val isVis = metadata.progressPercentage > 0
|
||||
progressText?.isVisible = isVis
|
||||
if (isVis)
|
||||
progressText?.text = "${metadata.progressPercentage}%"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.lagradost.cloudstream3.ui.download
|
||||
|
||||
import com.lagradost.cloudstream3.AcraApplication
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.KEY_DOWNLOAD_INFO
|
||||
import com.lagradost.fetchbutton.aria2c.Aria2Starter
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadListener
|
||||
import com.lagradost.fetchbutton.aria2c.Metadata
|
||||
import java.io.File
|
||||
|
||||
const val KEY_DOWNLOAD_INFO_METADATA = "download_info_metadata"
|
||||
|
||||
object Aria2cHelper {
|
||||
fun deleteId(id: Long) {
|
||||
// backward compatibility
|
||||
VideoDownloadManager.downloadDeleteEvent.invoke(id.toInt())
|
||||
|
||||
getMetadata(id)?.let { data ->
|
||||
Aria2Starter.delete(
|
||||
DownloadListener.sessionIdToGid[id],
|
||||
id,
|
||||
data.items.flatMap { it.files })
|
||||
}
|
||||
removeMetadata(id)
|
||||
AcraApplication.removeKey(KEY_DOWNLOAD_INFO, id.toString())
|
||||
}
|
||||
|
||||
fun saveMetadata(id: Long, meta: Metadata) {
|
||||
AcraApplication.setKey(KEY_DOWNLOAD_INFO_METADATA, id.toString(), meta)
|
||||
}
|
||||
|
||||
fun removeMetadata(id: Long) {
|
||||
AcraApplication.removeKey(KEY_DOWNLOAD_INFO_METADATA, id.toString())
|
||||
}
|
||||
|
||||
fun downloadExist(data: Metadata): Boolean {
|
||||
return data.items.any {
|
||||
it.files.any { file ->
|
||||
try {
|
||||
//println("TESTING PATH: ${file.path}")
|
||||
File(file.path).exists()
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadExist(id: Long): Boolean {
|
||||
return downloadExist(getMetadata(id) ?: return false)
|
||||
}
|
||||
|
||||
fun getMetadata(id: Long): Metadata? {
|
||||
return AcraApplication.getKey(KEY_DOWNLOAD_INFO_METADATA, id.toString())
|
||||
}
|
||||
|
||||
fun pause(id: Long) {
|
||||
DownloadListener.sessionIdToGid[id]?.let { gid ->
|
||||
Aria2Starter.pause(gid, all = true)
|
||||
}
|
||||
}
|
||||
|
||||
fun unpause(id: Long) {
|
||||
DownloadListener.sessionIdToGid[id]?.let { gid ->
|
||||
Aria2Starter.unpause(gid, all = true)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,22 +2,160 @@ package com.lagradost.cloudstream3.ui.download
|
|||
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.text.format.Formatter
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.doOnAttach
|
||||
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadListener
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
|
||||
object DownloadButtonSetup {
|
||||
fun bind(
|
||||
card: IVisualDownloadChildCached,
|
||||
downloadButton: PieFetchButton,
|
||||
extraInfo: TextView,
|
||||
clickCallback: (DownloadClickEvent) -> Unit
|
||||
) {
|
||||
val d = card.data ?: return
|
||||
|
||||
fun updateText(downloadBytes: Long, totalBytes: Long) {
|
||||
extraInfo?.apply {
|
||||
text =
|
||||
context.getString(R.string.download_size_format).format(
|
||||
Formatter.formatShortFileSize(context, downloadBytes),
|
||||
Formatter.formatShortFileSize(context, totalBytes)
|
||||
)
|
||||
}
|
||||
}
|
||||
updateText(card.currentBytes, card.totalBytes)
|
||||
downloadButton.apply {
|
||||
val play =
|
||||
if (card is VisualDownloadChildCached) R.string.play_episode else R.string.play_movie_button//if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode
|
||||
|
||||
setPersistentId(d.id.toLong())
|
||||
doOnAttach { view ->
|
||||
view.findViewTreeLifecycleOwner()?.let { life ->
|
||||
DownloadListener.observe(life) {
|
||||
gid?.let { realGId ->
|
||||
val meta = DownloadListener.getInfo(realGId)
|
||||
updateText(meta.downloadedLength, meta.totalLength)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val isValid = when (downloadButton.currentStatus) {
|
||||
null, DownloadStatusTell.Removed -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
|
||||
downloadButton.setOnClickListener {
|
||||
val view = downloadButton
|
||||
|
||||
fun delete() {
|
||||
// view.deleteAllFiles()
|
||||
clickCallback.invoke(
|
||||
DownloadClickEvent(
|
||||
DOWNLOAD_ACTION_DELETE_FILE,
|
||||
d
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
//if (view !is PieFetchButton) return@setOnClickListener
|
||||
when (view.currentStatus) {
|
||||
/*null, DownloadStatusTell.Removed -> {
|
||||
view.setStatus(DownloadStatusTell.Waiting)
|
||||
downloadClickCallback.invoke(
|
||||
DownloadEpisodeClickEvent(
|
||||
DOWNLOAD_ACTION_DOWNLOAD,
|
||||
card
|
||||
)
|
||||
)
|
||||
}*/
|
||||
DownloadStatusTell.Paused -> {
|
||||
view.popupMenuNoIcons(
|
||||
if (isValid) listOf(
|
||||
1 to R.string.resume,
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
) else listOf(2 to play, 3 to R.string.delete)
|
||||
) {
|
||||
when (itemId) {
|
||||
1 -> if (!view.resumeDownload()) {
|
||||
/*downloadClickCallback.invoke(
|
||||
DownloadEpisodeClickEvent(
|
||||
DOWNLOAD_ACTION_DOWNLOAD,
|
||||
card
|
||||
)
|
||||
)*/
|
||||
}
|
||||
2 -> play(d)
|
||||
3 -> delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Complete -> {
|
||||
view.popupMenuNoIcons(
|
||||
listOf(
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
)
|
||||
) {
|
||||
when (itemId) {
|
||||
2 -> play(d)
|
||||
3 -> delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Active -> {
|
||||
view.popupMenuNoIcons(
|
||||
if (isValid) listOf(
|
||||
4 to R.string.pause,
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
) else listOf(
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
)
|
||||
) {
|
||||
when (itemId) {
|
||||
4 -> view.pauseDownload()
|
||||
2 -> play(d)
|
||||
3 -> delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Error -> {
|
||||
view.redownload()
|
||||
}
|
||||
DownloadStatusTell.Waiting -> {
|
||||
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleDownloadClick(activity: Activity?, click: DownloadClickEvent) {
|
||||
val id = click.data.id
|
||||
if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return
|
||||
|
@ -29,6 +167,7 @@ object DownloadButtonSetup {
|
|||
DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
Aria2cHelper.deleteId(id.toLong())
|
||||
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
||||
}
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
|
@ -57,11 +196,14 @@ object DownloadButtonSetup {
|
|||
}
|
||||
}
|
||||
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
||||
Aria2cHelper.pause(click.data.id.toLong())
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
||||
)
|
||||
}
|
||||
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
||||
Aria2cHelper.unpause(click.data.id.toLong())
|
||||
|
||||
activity?.let { ctx ->
|
||||
if (VideoDownloadManager.downloadStatus.containsKey(id) && VideoDownloadManager.downloadStatus[id] == VideoDownloadManager.DownloadType.IsPaused) {
|
||||
VideoDownloadManager.downloadEvent.invoke(
|
||||
|
@ -86,6 +228,7 @@ object DownloadButtonSetup {
|
|||
act,
|
||||
click.data.id
|
||||
)?.fileLength
|
||||
?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength
|
||||
?: 0
|
||||
if (length > 0) {
|
||||
showToast(act, R.string.delete, Toast.LENGTH_LONG)
|
||||
|
|
|
@ -3,18 +3,20 @@ package com.lagradost.cloudstream3.ui.download
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.ContentLoadingProgressBar
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
||||
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
||||
import java.util.*
|
||||
|
||||
const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
||||
const val DOWNLOAD_ACTION_DELETE_FILE = 1
|
||||
|
@ -23,52 +25,31 @@ const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3
|
|||
const val DOWNLOAD_ACTION_DOWNLOAD = 4
|
||||
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
||||
|
||||
interface IVisualDownloadChildCached{
|
||||
val currentBytes: Long
|
||||
val totalBytes: Long
|
||||
val data: VideoDownloadHelper.DownloadEpisodeCached?
|
||||
}
|
||||
|
||||
data class VisualDownloadChildCached(
|
||||
val currentBytes: Long,
|
||||
val totalBytes: Long,
|
||||
val data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||
)
|
||||
override val currentBytes: Long,
|
||||
override val totalBytes: Long,
|
||||
override val data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||
) : IVisualDownloadChildCached
|
||||
|
||||
data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData)
|
||||
data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||
|
||||
class DownloadChildAdapter(
|
||||
var cardList: List<VisualDownloadChildCached>,
|
||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
|
||||
private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? {
|
||||
return Collections.unmodifiableSet(mBoundViewHolders)
|
||||
}
|
||||
|
||||
fun killAdapter() {
|
||||
getAllBoundViewHolders()?.forEach { view ->
|
||||
view?.downloadButton?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.downloadButton.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.downloadButton.dispose()
|
||||
mBoundViewHolders.remove(holder)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.reattachDownloadButton()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return DownloadChildViewHolder(
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.download_child_episode, parent, false),
|
||||
LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.download_child_episode, parent, false),
|
||||
clickCallback
|
||||
)
|
||||
}
|
||||
|
@ -77,7 +58,6 @@ class DownloadChildAdapter(
|
|||
when (holder) {
|
||||
is DownloadChildViewHolder -> {
|
||||
holder.bind(cardList[position])
|
||||
mBoundViewHolders.add(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,15 +70,13 @@ class DownloadChildAdapter(
|
|||
constructor(
|
||||
itemView: View,
|
||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
||||
override var downloadButton = EasyDownloadButton()
|
||||
|
||||
) : 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
|
||||
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
|
||||
private val downloadImage: ImageView = itemView.download_child_episode_download
|
||||
private val progressBar: ContentLoadingProgressBar =
|
||||
itemView.download_child_episode_progress
|
||||
private val downloadButton: PieFetchButton = itemView.download_child_episode_download
|
||||
|
||||
private var localCard: VisualDownloadChildCached? = null
|
||||
|
||||
|
@ -118,35 +96,17 @@ class DownloadChildAdapter(
|
|||
|
||||
title.text = title.context.getNameFull(d.name, d.episode, d.season)
|
||||
title.isSelected = true // is needed for text repeating
|
||||
//extraInfo.text = card.currentBytes
|
||||
DownloadButtonSetup.bind(card, downloadButton, extraInfo, clickCallback)
|
||||
|
||||
downloadButton.setUpButton(
|
||||
card.currentBytes,
|
||||
card.totalBytes,
|
||||
progressBarDownload,
|
||||
downloadImage,
|
||||
extraInfo,
|
||||
card.data,
|
||||
clickCallback
|
||||
)
|
||||
|
||||
holder.setOnClickListener {
|
||||
if (downloadButton.isVisible) {
|
||||
downloadButton.play(d)
|
||||
} else {
|
||||
holder.setOnClickListener {
|
||||
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
||||
}
|
||||
}
|
||||
|
||||
override fun reattachDownloadButton() {
|
||||
downloadButton.dispose()
|
||||
val card = localCard
|
||||
if (card != null) {
|
||||
downloadButton.setUpButton(
|
||||
card.currentBytes,
|
||||
card.totalBytes,
|
||||
progressBarDownload,
|
||||
downloadImage,
|
||||
extraInfo,
|
||||
card.data,
|
||||
clickCallback
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ 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.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||
|
@ -21,7 +22,7 @@ import kotlinx.coroutines.withContext
|
|||
|
||||
class DownloadChildFragment : Fragment() {
|
||||
companion object {
|
||||
fun newInstance(headerName: String, folder: String) : Bundle {
|
||||
fun newInstance(headerName: String, folder: String): Bundle {
|
||||
return Bundle().apply {
|
||||
putString("folder", folder)
|
||||
putString("name", headerName)
|
||||
|
@ -30,15 +31,18 @@ class DownloadChildFragment : Fragment() {
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
(download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter()
|
||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
||||
}
|
||||
|
||||
private var hasPopped = false // fix stupid bug
|
||||
private fun updateList(folder: String) = main {
|
||||
context?.let { ctx ->
|
||||
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
||||
|
@ -50,9 +54,11 @@ class DownloadChildFragment : Fragment() {
|
|||
?: return@mapNotNull null
|
||||
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
||||
}
|
||||
}.sortedBy { it.data.episode + (it.data.season?: 0)*100000 }
|
||||
if (eps.isEmpty()) {
|
||||
activity?.onBackPressed()
|
||||
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
||||
|
||||
if (eps.isEmpty() && !hasPopped) {
|
||||
hasPopped = true
|
||||
activity?.popCurrentPage()
|
||||
return@main
|
||||
}
|
||||
|
||||
|
@ -85,6 +91,13 @@ class DownloadChildFragment : Fragment() {
|
|||
ArrayList(),
|
||||
) { click ->
|
||||
handleDownloadClick(activity, click)
|
||||
/* println("HANDLE ACTION :${click.action}")
|
||||
if (click.action == DOWNLOAD_ACTION_DELETE_FILE) {
|
||||
val list = (download_child_list?.adapter as DownloadChildAdapter?)?.cardList
|
||||
if (list != null) {
|
||||
updateList(folder)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
downloadDeleteEventListener = { id: Int ->
|
||||
|
|
|
@ -69,7 +69,6 @@ class DownloadFragment : Fragment() {
|
|||
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
||||
downloadDeleteEventListener = null
|
||||
}
|
||||
(download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
@ -165,7 +164,7 @@ class DownloadFragment : Fragment() {
|
|||
downloadDeleteEventListener = { id ->
|
||||
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
||||
if (list != null) {
|
||||
if (list.any { it.data.id == id }) {
|
||||
if (list.any { it.data?.id == id }) {
|
||||
context?.let { ctx ->
|
||||
setList(ArrayList())
|
||||
downloadsViewModel.updateList(ctx)
|
||||
|
|
|
@ -8,23 +8,25 @@ import android.view.ViewGroup
|
|||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.ContentLoadingProgressBar
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
||||
import java.util.*
|
||||
|
||||
data class VisualDownloadHeaderCached(
|
||||
val currentOngoingDownloads: Int,
|
||||
val totalDownloads: Int,
|
||||
val totalBytes: Long,
|
||||
val currentBytes: Long,
|
||||
val data: VideoDownloadHelper.DownloadHeaderCached,
|
||||
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||
)
|
||||
override val totalBytes: Long,
|
||||
override val currentBytes: Long,
|
||||
val header: VideoDownloadHelper.DownloadHeaderCached,
|
||||
override val data: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||
) : IVisualDownloadChildCached
|
||||
|
||||
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
||||
|
||||
|
@ -34,35 +36,6 @@ class DownloadHeaderAdapter(
|
|||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
|
||||
private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? {
|
||||
return Collections.unmodifiableSet(mBoundViewHolders)
|
||||
}
|
||||
|
||||
fun killAdapter() {
|
||||
getAllBoundViewHolders()?.forEach { view ->
|
||||
view?.downloadButton?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.downloadButton.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.downloadButton.dispose()
|
||||
mBoundViewHolders.remove(holder)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.reattachDownloadButton()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return DownloadHeaderViewHolder(
|
||||
|
@ -76,7 +49,6 @@ class DownloadHeaderAdapter(
|
|||
when (holder) {
|
||||
is DownloadHeaderViewHolder -> {
|
||||
holder.bind(cardList[position])
|
||||
mBoundViewHolders.add(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,23 +62,17 @@ class DownloadHeaderAdapter(
|
|||
itemView: View,
|
||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
||||
override var downloadButton = EasyDownloadButton()
|
||||
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
private val poster: ImageView? = itemView.download_header_poster
|
||||
private val title: TextView = itemView.download_header_title
|
||||
private val extraInfo: TextView = itemView.download_header_info
|
||||
private val holder: CardView = itemView.episode_holder
|
||||
|
||||
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
|
||||
private val downloadImage: ImageView = itemView.download_header_episode_download
|
||||
private val normalImage: ImageView = itemView.download_header_goto_child
|
||||
private var localCard: VisualDownloadHeaderCached? = null
|
||||
private val downloadButton: PieFetchButton = itemView.download_header_download
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(card: VisualDownloadHeaderCached) {
|
||||
localCard = card
|
||||
val d = card.data
|
||||
val d = card.header
|
||||
|
||||
poster?.setImage(d.poster)
|
||||
poster?.setOnClickListener {
|
||||
|
@ -117,10 +83,8 @@ class DownloadHeaderAdapter(
|
|||
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
||||
|
||||
//val isMovie = d.type.isMovieType()
|
||||
if (card.child != null) {
|
||||
downloadBar.visibility = View.VISIBLE
|
||||
downloadImage.visibility = View.VISIBLE
|
||||
normalImage.visibility = View.GONE
|
||||
if (card.data != null) {
|
||||
downloadButton.isVisible = true
|
||||
/*setUpButton(
|
||||
card.currentBytes,
|
||||
card.totalBytes,
|
||||
|
@ -130,14 +94,15 @@ class DownloadHeaderAdapter(
|
|||
card.child,
|
||||
movieClickCallback
|
||||
)*/
|
||||
DownloadButtonSetup.bind(card, downloadButton, extraInfo) { click ->
|
||||
movieClickCallback.invoke(DownloadClickEvent(click.action, card.data))
|
||||
}
|
||||
|
||||
holder.setOnClickListener {
|
||||
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
||||
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.data))
|
||||
}
|
||||
} else {
|
||||
downloadBar.visibility = View.GONE
|
||||
downloadImage.visibility = View.GONE
|
||||
normalImage.visibility = View.VISIBLE
|
||||
downloadButton.isVisible = false
|
||||
|
||||
try {
|
||||
extraInfo.text =
|
||||
|
@ -160,21 +125,5 @@ class DownloadHeaderAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun reattachDownloadButton() {
|
||||
downloadButton.dispose()
|
||||
val card = localCard
|
||||
if (card?.child != null) {
|
||||
downloadButton.setUpButton(
|
||||
card.currentBytes,
|
||||
card.totalBytes,
|
||||
downloadBar,
|
||||
downloadImage,
|
||||
extraInfo,
|
||||
card.child,
|
||||
movieClickCallback
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package com.lagradost.cloudstream3.ui.download
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
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.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.CommonActivity
|
||||
import com.lagradost.cloudstream3.isMovieType
|
||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
|
@ -46,6 +49,8 @@ class DownloadViewModel : ViewModel() {
|
|||
.distinctBy { it.id } // Remove duplicates
|
||||
}
|
||||
|
||||
println("CHILDRE:$children")
|
||||
|
||||
// parentId : bytes
|
||||
val totalBytesUsedByChild = HashMap<Int, Long>()
|
||||
// parentId : bytes
|
||||
|
@ -53,12 +58,10 @@ class DownloadViewModel : ViewModel() {
|
|||
// 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) ?: continue
|
||||
|
||||
if (childFile.fileLength <= 1) continue
|
||||
val len = childFile.totalBytes
|
||||
val flen = childFile.fileLength
|
||||
|
@ -68,7 +71,8 @@ class DownloadViewModel : ViewModel() {
|
|||
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
||||
}
|
||||
}
|
||||
|
||||
println("TotalDownloads:$totalDownloads")
|
||||
//println("FIXED: $totalDownloads")
|
||||
val cached = withContext(Dispatchers.IO) { // wont fetch useless keys
|
||||
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
||||
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
||||
|
@ -77,6 +81,7 @@ class DownloadViewModel : ViewModel() {
|
|||
)
|
||||
}
|
||||
}
|
||||
println("Cached:$cached")
|
||||
|
||||
val visual = withContext(Dispatchers.IO) {
|
||||
cached.mapNotNull { // TODO FIX
|
||||
|
@ -99,7 +104,7 @@ class DownloadViewModel : ViewModel() {
|
|||
movieEpisode
|
||||
)
|
||||
}.sortedBy {
|
||||
(it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0)
|
||||
(it.data?.episode ?: 0) + (it.data?.season?.times(10000) ?: 0)
|
||||
} // episode sorting by episode, lowest to highest
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
package com.lagradost.cloudstream3.ui.result
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadEpisodeClickEvent
|
||||
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.fetchbutton.aria2c.Aria2Starter
|
||||
import com.lagradost.fetchbutton.aria2c.DownloadStatusTell
|
||||
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
import java.io.File
|
||||
|
||||
object DownloadHelper {
|
||||
fun PieFetchButton.play(card: VideoDownloadHelper.DownloadEpisodeCached) {
|
||||
val files = this.getVideos()
|
||||
// fucked af, but who cares
|
||||
Aria2Starter.saveActivity.get()?.navigate(
|
||||
R.id.global_to_navigation_player, GeneratorPlayer.newInstance(DownloadFileGenerator(
|
||||
files.map { path ->
|
||||
val file = File(path)
|
||||
|
||||
ExtractorUri(
|
||||
uri = file.toUri(),
|
||||
|
||||
id = card.id,
|
||||
parentId = card.parentId,
|
||||
name = context.getString(R.string.downloaded_file), //click.data.name ?: keyInfo.displayName
|
||||
season = card.season,
|
||||
episode = card.episode,
|
||||
|
||||
basePath = file.path,
|
||||
displayName = file.name
|
||||
//displayName = keyInfo.displayName,
|
||||
//relativePath = keyInfo.relativePath,
|
||||
)
|
||||
}
|
||||
)))
|
||||
}
|
||||
|
||||
fun PieFetchButton.play(card: ResultEpisode) {
|
||||
val files = this.getVideos()
|
||||
// fucked af, but who cares
|
||||
Aria2Starter.saveActivity.get()?.navigate(
|
||||
|
||||
R.id.global_to_navigation_player, GeneratorPlayer.newInstance(DownloadFileGenerator(
|
||||
files.map { path ->
|
||||
val file = File(path)
|
||||
|
||||
ExtractorUri(
|
||||
uri = file.toUri(),
|
||||
|
||||
id = card.id,
|
||||
parentId = card.parentId,
|
||||
name = context.getString(R.string.downloaded_file), //click.data.name ?: keyInfo.displayName
|
||||
season = card.season,
|
||||
episode = card.episode,
|
||||
headerName = card.headerName,
|
||||
tvType = card.tvType,
|
||||
|
||||
basePath = file.path,
|
||||
displayName = file.name,
|
||||
//relativePath = keyInfo.relativePath,
|
||||
)
|
||||
}
|
||||
)))
|
||||
}
|
||||
|
||||
fun PieFetchButton.setUp(
|
||||
card: ResultEpisode,
|
||||
downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit
|
||||
) {
|
||||
setPersistentId(card.id.toLong())
|
||||
val play = if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode
|
||||
|
||||
setOnLongClickListener { //Aria2Starter.saveActivity.get()
|
||||
downloadClickCallback.invoke(
|
||||
DownloadEpisodeClickEvent(
|
||||
DOWNLOAD_ACTION_LONG_CLICK,
|
||||
card
|
||||
)
|
||||
)
|
||||
//showToast(it.context as? Activity, R.string.download, Toast.LENGTH_SHORT)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
setOnClickListener {
|
||||
val view = this
|
||||
//if (view !is PieFetchButton) return@setOnClickListener
|
||||
when (view.currentStatus) {
|
||||
null, DownloadStatusTell.Removed -> {
|
||||
view.setStatus(DownloadStatusTell.Waiting)
|
||||
downloadClickCallback.invoke(
|
||||
DownloadEpisodeClickEvent(
|
||||
DOWNLOAD_ACTION_DOWNLOAD,
|
||||
card
|
||||
)
|
||||
)
|
||||
}
|
||||
DownloadStatusTell.Paused -> {
|
||||
view.popupMenuNoIcons(
|
||||
listOf(
|
||||
1 to R.string.resume,
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
)
|
||||
) {
|
||||
when (itemId) {
|
||||
1 -> if (!view.resumeDownload()) {
|
||||
downloadClickCallback.invoke(
|
||||
DownloadEpisodeClickEvent(
|
||||
DOWNLOAD_ACTION_DOWNLOAD,
|
||||
card
|
||||
)
|
||||
)
|
||||
}
|
||||
2 -> play(card)
|
||||
3 -> view.deleteAllFiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Complete -> {
|
||||
view.popupMenuNoIcons(
|
||||
listOf(
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
)
|
||||
) {
|
||||
when (itemId) {
|
||||
2 -> play(card)
|
||||
3 -> view.deleteAllFiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Active -> {
|
||||
view.popupMenuNoIcons(
|
||||
listOf(
|
||||
4 to R.string.pause,
|
||||
2 to play,
|
||||
3 to R.string.delete
|
||||
)
|
||||
) {
|
||||
when (itemId) {
|
||||
4 -> view.pauseDownload()
|
||||
2 -> play(card)
|
||||
3 -> view.deleteAllFiles()
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadStatusTell.Error -> {
|
||||
view.redownload()
|
||||
}
|
||||
DownloadStatusTell.Waiting -> {
|
||||
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -13,23 +13,17 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
||||
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadEpisodeClickEvent
|
||||
import com.lagradost.cloudstream3.ui.result.DownloadHelper.setUp
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import kotlinx.android.synthetic.main.result_episode.view.*
|
||||
import kotlinx.android.synthetic.main.result_episode.view.episode_text
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.*
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.episode_filler
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.episode_progress
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_download
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_progress_downloaded
|
||||
import java.util.*
|
||||
import kotlinx.android.synthetic.main.result_episode_large_tv.view.*
|
||||
|
||||
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||
const val ACTION_PLAY_EPISODE_IN_VLC_PLAYER = 2
|
||||
|
@ -58,21 +52,10 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
|||
class EpisodeAdapter(
|
||||
private val hasDownloadSupport: Boolean,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit,
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
private var cardList: MutableList<ResultEpisode> = mutableListOf()
|
||||
|
||||
private val mBoundViewHolders: HashSet<DownloadButtonViewHolder> = HashSet()
|
||||
private fun getAllBoundViewHolders(): Set<DownloadButtonViewHolder?>? {
|
||||
return Collections.unmodifiableSet(mBoundViewHolders)
|
||||
}
|
||||
|
||||
fun killAdapter() {
|
||||
getAllBoundViewHolders()?.forEach { view ->
|
||||
view?.downloadButton?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder.itemView.hasFocus()) {
|
||||
holder.itemView.clearFocus()
|
||||
|
@ -85,15 +68,6 @@ class EpisodeAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
holder.downloadButton.dispose()
|
||||
mBoundViewHolders.remove(holder)
|
||||
//(holder.itemView as? FrameLayout?)?.descendantFocusability =
|
||||
// ViewGroup.FOCUS_BLOCK_DESCENDANTS
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is DownloadButtonViewHolder) {
|
||||
//println("onViewAttachedToWindow = ${holder.absoluteAdapterPosition}")
|
||||
|
@ -138,7 +112,6 @@ class EpisodeAdapter(
|
|||
when (holder) {
|
||||
is EpisodeCardViewHolder -> {
|
||||
holder.bind(cardList[position])
|
||||
mBoundViewHolders.add(holder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,18 +125,12 @@ class EpisodeAdapter(
|
|||
itemView: View,
|
||||
private val hasDownloadSupport: Boolean,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
||||
override var downloadButton = EasyDownloadButton()
|
||||
|
||||
var episodeDownloadBar: ContentLoadingProgressBar? = null
|
||||
var episodeDownloadImage: ImageView? = null
|
||||
var localCard: ResultEpisode? = null
|
||||
private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
//override var downloadButton = EasyDownloadButton()
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
fun bind(card: ResultEpisode) {
|
||||
localCard = card
|
||||
|
||||
val isTrueTv = isTrueTvSettings()
|
||||
|
||||
val (parentView, otherView) = if (card.poster == null) {
|
||||
|
@ -181,9 +148,10 @@ class EpisodeAdapter(
|
|||
val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress
|
||||
val episodePoster: ImageView? = parentView.episode_poster
|
||||
|
||||
episodeDownloadBar =
|
||||
parentView.result_episode_progress_downloaded
|
||||
episodeDownloadImage = parentView.result_episode_download
|
||||
val downloadButton = parentView.result_episode_download
|
||||
|
||||
downloadButton.isVisible = hasDownloadSupport
|
||||
downloadButton.setUp(card, downloadClickCallback)
|
||||
|
||||
val name =
|
||||
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}"
|
||||
|
@ -242,49 +210,6 @@ class EpisodeAdapter(
|
|||
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
episodeDownloadImage?.isVisible = hasDownloadSupport
|
||||
episodeDownloadBar?.isVisible = hasDownloadSupport
|
||||
reattachDownloadButton()
|
||||
}
|
||||
|
||||
override fun reattachDownloadButton() {
|
||||
downloadButton.dispose()
|
||||
val card = localCard
|
||||
if (hasDownloadSupport && card != null) {
|
||||
if (episodeDownloadBar == null ||
|
||||
episodeDownloadImage == null
|
||||
) return
|
||||
val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
||||
itemView.context,
|
||||
card.id
|
||||
)
|
||||
|
||||
downloadButton.setUpButton(
|
||||
downloadInfo?.fileLength,
|
||||
downloadInfo?.totalBytes,
|
||||
episodeDownloadBar ?: return,
|
||||
episodeDownloadImage ?: return,
|
||||
null,
|
||||
VideoDownloadHelper.DownloadEpisodeCached(
|
||||
card.name,
|
||||
card.poster,
|
||||
card.episode,
|
||||
card.season,
|
||||
card.id,
|
||||
card.parentId,
|
||||
card.rating,
|
||||
card.description,
|
||||
System.currentTimeMillis(),
|
||||
)
|
||||
) {
|
||||
if (it.action == DOWNLOAD_ACTION_DOWNLOAD) {
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card))
|
||||
} else {
|
||||
downloadClickCallback.invoke(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,20 +35,20 @@ import com.lagradost.cloudstream3.mvvm.*
|
|||
import com.lagradost.cloudstream3.syncproviders.providers.Kitsu
|
||||
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.download.EasyDownloadButton
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
|
||||
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
||||
import com.lagradost.cloudstream3.ui.result.DownloadHelper.setUp
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
||||
import com.lagradost.cloudstream3.utils.UIHelper
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
||||
|
@ -72,11 +72,6 @@ import kotlinx.android.synthetic.main.fragment_result.result_meta_rating
|
|||
import kotlinx.android.synthetic.main.fragment_result.result_meta_site
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_meta_type
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_meta_year
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_icon
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text_precentage
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded_holder
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_next_airing
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_next_airing_time
|
||||
import kotlinx.android.synthetic.main.fragment_result.result_no_episodes
|
||||
|
@ -253,11 +248,8 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
return inflater.inflate(resultLayout, container, false)
|
||||
}
|
||||
|
||||
private var downloadButton: EasyDownloadButton? = null
|
||||
override fun onDestroyView() {
|
||||
updateUIListener = null
|
||||
(result_episodes?.adapter as EpisodeAdapter?)?.killAdapter()
|
||||
downloadButton?.dispose()
|
||||
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -344,7 +336,18 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
main {
|
||||
|
||||
result_download_movie?.setUp(ep) {
|
||||
when (it.action) {
|
||||
DOWNLOAD_ACTION_DOWNLOAD -> viewModel.download(activity, it.data)
|
||||
DOWNLOAD_ACTION_LONG_CLICK -> viewModel.handleAction(
|
||||
activity,
|
||||
EpisodeClickEvent(ACTION_DOWNLOAD_MIRROR, ep)
|
||||
)
|
||||
}
|
||||
}
|
||||
result_download_movie?.isVisible = true
|
||||
/*main {
|
||||
val file =
|
||||
ioWorkSafe {
|
||||
context?.let {
|
||||
|
@ -389,11 +392,12 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
}
|
||||
}
|
||||
result_movie_progress_downloaded_holder?.isVisible = true
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
result_movie_progress_downloaded_holder?.isVisible = false
|
||||
//result_movie_progress_downloaded_holder?.isVisible = false
|
||||
result_download_movie?.isVisible = false
|
||||
result_play_movie?.isVisible = false
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +462,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
val storedData = getStoredData(activity ?: context ?: return) ?: return
|
||||
|
||||
//viewModel.clear()
|
||||
viewModel.load(activity, storedData.url ?: return, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start)
|
||||
viewModel.load(
|
||||
activity,
|
||||
storedData.url ?: return,
|
||||
storedData.apiName,
|
||||
storedData.showFillers,
|
||||
storedData.dubStatus,
|
||||
storedData.start
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,8 +518,15 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
{ episodeClick ->
|
||||
viewModel.handleAction(activity, episodeClick)
|
||||
},
|
||||
{ downloadClickEvent ->
|
||||
handleDownloadClick(activity, downloadClickEvent)
|
||||
{ clickEvent ->
|
||||
when (clickEvent.action) {
|
||||
DOWNLOAD_ACTION_DOWNLOAD -> viewModel.download(activity, clickEvent.data)
|
||||
DOWNLOAD_ACTION_LONG_CLICK -> viewModel.handleAction(
|
||||
activity,
|
||||
EpisodeClickEvent(ACTION_DOWNLOAD_MIRROR, clickEvent.data)
|
||||
)
|
||||
}
|
||||
//handleDownloadClick(activity, downloadClickEvent)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -916,7 +934,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
|
||||
if (storedData?.url != null) {
|
||||
result_reload_connectionerror.setOnClickListener {
|
||||
viewModel.load(activity, storedData.url, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start)
|
||||
viewModel.load(
|
||||
activity,
|
||||
storedData.url,
|
||||
storedData.apiName,
|
||||
storedData.showFillers,
|
||||
storedData.dubStatus,
|
||||
storedData.start
|
||||
)
|
||||
}
|
||||
|
||||
result_reload_connection_open_in_browser?.setOnClickListener {
|
||||
|
@ -952,7 +977,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
|||
|
||||
if (restart || !viewModel.hasLoaded()) {
|
||||
//viewModel.clear()
|
||||
viewModel.load(activity, storedData.url, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start)
|
||||
viewModel.load(
|
||||
activity,
|
||||
storedData.url,
|
||||
storedData.apiName,
|
||||
storedData.showFillers,
|
||||
storedData.dubStatus,
|
||||
storedData.start
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.getId
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTime
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.getCastSession
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
|
@ -28,7 +30,6 @@ import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
|||
import com.lagradost.cloudstream3.syncproviders.providers.Kitsu
|
||||
import com.lagradost.cloudstream3.ui.APIRepository
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||
import com.lagradost.cloudstream3.ui.player.IGenerator
|
||||
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator
|
||||
|
@ -53,8 +54,14 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setDub
|
|||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultEpisode
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||
import com.lagradost.fetchbutton.NotificationMetaData
|
||||
import com.lagradost.fetchbutton.aria2c.Aria2Starter
|
||||
import com.lagradost.fetchbutton.aria2c.UriRequest
|
||||
import com.lagradost.fetchbutton.aria2c.newUriRequest
|
||||
import com.lagradost.fetchbutton.utils.Coroutines.mainThread
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import java.lang.Math.abs
|
||||
|
@ -529,24 +536,16 @@ class ResultViewModel2 : ViewModel() {
|
|||
}
|
||||
|
||||
private fun downloadSubtitle(
|
||||
context: Context?,
|
||||
link: ExtractorSubtitleLink,
|
||||
fileName: String,
|
||||
folder: String
|
||||
) {
|
||||
ioSafe {
|
||||
VideoDownloadManager.downloadThing(
|
||||
context ?: return@ioSafe,
|
||||
link,
|
||||
"$fileName ${link.name}",
|
||||
folder,
|
||||
if (link.url.contains(".srt")) ".srt" else "vtt",
|
||||
false,
|
||||
null
|
||||
) {
|
||||
// no notification
|
||||
}
|
||||
}
|
||||
Aria2Starter.download(
|
||||
newUriRequest(
|
||||
null, link.url, fileName, folder, link.headers,
|
||||
USER_AGENT
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getFolder(currentType: TvType, titleName: String): String {
|
||||
|
@ -576,7 +575,6 @@ class ResultViewModel2 : ViewModel() {
|
|||
val fileName = VideoDownloadManager.getFileName(ctx, meta)
|
||||
val folder = getFolder(meta.type ?: return, meta.mainName)
|
||||
downloadSubtitle(
|
||||
ctx,
|
||||
ExtractorSubtitleLink(link.name, link.url, ""),
|
||||
fileName,
|
||||
folder
|
||||
|
@ -584,8 +582,7 @@ class ResultViewModel2 : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
fun startDownload(
|
||||
context: Context?,
|
||||
fun getDownloadRequest(
|
||||
episode: ResultEpisode,
|
||||
currentIsMovie: Boolean,
|
||||
currentHeaderName: String,
|
||||
|
@ -596,10 +593,7 @@ class ResultViewModel2 : ViewModel() {
|
|||
url: String,
|
||||
links: List<ExtractorLink>,
|
||||
subs: List<SubtitleData>?
|
||||
) {
|
||||
try {
|
||||
if (context == null) return
|
||||
|
||||
): DownloadRequest? {
|
||||
val meta =
|
||||
getMeta(
|
||||
episode,
|
||||
|
@ -610,9 +604,15 @@ class ResultViewModel2 : ViewModel() {
|
|||
currentType
|
||||
)
|
||||
|
||||
val folder = getFolder(currentType, currentHeaderName)
|
||||
val topFolder = VideoDownloadManager.getDownloadDir()?.filePath
|
||||
?: throw RuntimeException("FUCK YOU")//AcraApplication.context?.getBasePath()?.first //?.second?.also { println("URIIIIII: $it") } ?: throw RuntimeException("FUCK YOU")
|
||||
//?: VideoDownloadManager.getDownloadDir()?.filePath ?: return null
|
||||
|
||||
val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
|
||||
val folder =
|
||||
topFolder//topFolder?.gotoDir(getFolder(currentType, currentHeaderName).replace(".", ""), true)?.uri?.toString() ?: throw RuntimeException("FUCK YOU")
|
||||
//val folder =
|
||||
// topFolder + "/" + getFolder(currentType, currentHeaderName).replace(".", "")
|
||||
//val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
|
||||
|
||||
// SET VISUAL KEYS
|
||||
AcraApplication.setKey(
|
||||
|
@ -648,41 +648,127 @@ class ResultViewModel2 : ViewModel() {
|
|||
)
|
||||
)
|
||||
|
||||
// DOWNLOAD VIDEO
|
||||
VideoDownloadManager.downloadEpisodeUsingWorker(
|
||||
context,
|
||||
src,//url ?: return,
|
||||
folder,
|
||||
meta,
|
||||
links
|
||||
val notification = AcraApplication.context?.let { ctx ->
|
||||
val rowTwoExtra = if (episode.name != null) " - ${episode.name}\n" else ""
|
||||
val rowTwo = if (episode.season != null && episode.episode > 0) {
|
||||
"${ctx.getString(R.string.season_short)}${episode.season}:${ctx.getString(R.string.episode_short)}${episode.episode}" + rowTwoExtra
|
||||
} else if (episode.episode > 0) {
|
||||
"${ctx.getString(R.string.episode)} ${episode.episode}" + rowTwoExtra
|
||||
} else {
|
||||
(episode.name ?: "") + ""
|
||||
}
|
||||
NotificationMetaData(
|
||||
episode.id,
|
||||
iconColor = ctx.colorFromAttribute(R.attr.colorPrimary),
|
||||
posterUrl = currentPoster,
|
||||
contentTitle = currentHeaderName,
|
||||
secondRow = rowTwo,
|
||||
subText = null,
|
||||
linkName = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
val linkRequests = links.filter { link -> !link.isM3u8 }.map { link ->
|
||||
newUriRequest(
|
||||
episode.id.toLong(), link.url,
|
||||
getFolder(currentType, currentHeaderName) + File.pathSeparator +
|
||||
VideoDownloadManager.getDisplayName(
|
||||
VideoDownloadManager.getFileName(
|
||||
AcraApplication.context ?: return null,
|
||||
meta
|
||||
), "mp4"
|
||||
), null, // we use the dir set at start
|
||||
link.headers, USER_AGENT,
|
||||
notificationMetaData = notification?.copy(
|
||||
linkName = "${link.name} ${
|
||||
Qualities.getStringByInt(
|
||||
link.quality
|
||||
)
|
||||
}"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// 1. Checks if the lang should be downloaded
|
||||
// 2. Makes it into the download format
|
||||
// 3. Downloads it as a .vtt file
|
||||
val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1()
|
||||
subs?.let { subsList ->
|
||||
subsList.filter {
|
||||
val downloadSubsList = (subs ?: emptyList()).filter {
|
||||
downloadList.contains(
|
||||
SubtitleHelper.fromLanguageToTwoLetters(
|
||||
it.name,
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
.map { ExtractorSubtitleLink(it.name, it.url, "") }
|
||||
.forEach { link ->
|
||||
val fileName = VideoDownloadManager.getFileName(context, meta)
|
||||
downloadSubtitle(context, link, fileName, folder)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}.distinctBy { it.url }.groupBy { link ->
|
||||
SubtitleHelper.fromLanguageToTwoLetters(
|
||||
link.name,
|
||||
true
|
||||
)
|
||||
}.map {
|
||||
it.value.map { link ->
|
||||
val fileName = VideoDownloadManager.getDisplayName(
|
||||
VideoDownloadManager.getFileName(
|
||||
AcraApplication.context ?: return null,
|
||||
meta
|
||||
), "vtt"
|
||||
)
|
||||
|
||||
newUriRequest(null, link.url, fileName, folder, link.headers, USER_AGENT)
|
||||
//downloadSubtitle(context, link, fileName, folder)
|
||||
}
|
||||
}
|
||||
|
||||
return DownloadRequest(linkRequests, downloadSubsList)
|
||||
|
||||
// DOWNLOAD VIDEO
|
||||
//VideoDownloadManager.downloadEpisodeUsingWorker(
|
||||
// context,
|
||||
// src,//url ?: return,
|
||||
// folder,
|
||||
// meta,
|
||||
// links
|
||||
//)
|
||||
|
||||
// 1. Checks if the lang should be downloaded
|
||||
// 2. Makes it into the download format
|
||||
// 3. Downloads it as a .vtt file
|
||||
//val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1()
|
||||
//subs?.let { subsList ->
|
||||
// subsList.filter {
|
||||
// downloadList.contains(
|
||||
// SubtitleHelper.fromLanguageToTwoLetters(
|
||||
// it.name,
|
||||
// true
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// .map { ExtractorSubtitleLink(it.name, it.url, "") }
|
||||
// .forEach { link ->
|
||||
// val fileName = VideoDownloadManager.getFileName(context, meta)
|
||||
// downloadSubtitle(context, link, fileName, folder)
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
data class DownloadRequest(
|
||||
val links: List<UriRequest>,
|
||||
val subs: List<List<UriRequest>>,
|
||||
)
|
||||
|
||||
|
||||
/*suspend fun download(episode: ResultEpisode): DownloadRequest {
|
||||
val generator = RepoLinkGenerator(listOf(episode))
|
||||
val currentLinks = mutableSetOf<ExtractorLink>()
|
||||
val currentSubs = mutableSetOf<SubtitleData>()
|
||||
generator.generateLinks(clearCache = false, isCasting = false, callback = {
|
||||
it.first?.let { link ->
|
||||
currentLinks.add(link)
|
||||
}
|
||||
}, subtitleCallback = { sub ->
|
||||
currentSubs.add(sub)
|
||||
})
|
||||
}*/
|
||||
|
||||
suspend fun downloadEpisode(
|
||||
activity: Activity?,
|
||||
episode: ResultEpisode,
|
||||
currentIsMovie: Boolean,
|
||||
currentHeaderName: String,
|
||||
|
@ -691,8 +777,7 @@ class ResultViewModel2 : ViewModel() {
|
|||
apiName: String,
|
||||
parentId: Int,
|
||||
url: String,
|
||||
) {
|
||||
ioSafe {
|
||||
): DownloadRequest? {
|
||||
val generator = RepoLinkGenerator(listOf(episode))
|
||||
val currentLinks = mutableSetOf<ExtractorLink>()
|
||||
val currentSubs = mutableSetOf<SubtitleData>()
|
||||
|
@ -704,27 +789,26 @@ class ResultViewModel2 : ViewModel() {
|
|||
currentSubs.add(sub)
|
||||
})
|
||||
|
||||
if (currentLinks.isEmpty()) {
|
||||
main {
|
||||
showToast(
|
||||
activity,
|
||||
R.string.no_links_found_toast,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
return@ioSafe
|
||||
} else {
|
||||
main {
|
||||
showToast(
|
||||
activity,
|
||||
R.string.download_started,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
}
|
||||
//if (currentLinks.isEmpty()) {
|
||||
// main {
|
||||
// showToast(
|
||||
// activity,
|
||||
// R.string.no_links_found_toast,
|
||||
// Toast.LENGTH_SHORT
|
||||
// )
|
||||
// }
|
||||
// return@ioSafe
|
||||
//} else {
|
||||
// main {
|
||||
// showToast(
|
||||
// activity,
|
||||
// R.string.download_started,
|
||||
// Toast.LENGTH_SHORT
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
|
||||
startDownload(
|
||||
activity,
|
||||
return getDownloadRequest(
|
||||
episode,
|
||||
currentIsMovie,
|
||||
currentHeaderName,
|
||||
|
@ -737,7 +821,6 @@ class ResultViewModel2 : ViewModel() {
|
|||
sortSubs(currentSubs),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMeta(
|
||||
episode: ResultEpisode,
|
||||
|
@ -1021,6 +1104,42 @@ class ResultViewModel2 : ViewModel() {
|
|||
handleEpisodeClickEvent(activity, click)
|
||||
}
|
||||
|
||||
private fun downloadFromRequest(activity: Activity?, req: DownloadRequest) {
|
||||
Aria2Starter.download(req.links)
|
||||
for (sub in req.subs.take(4)) { // download max 4 langs to not block real download
|
||||
Aria2Starter.download(sub)
|
||||
}
|
||||
val linksFound = req.links.isNotEmpty()
|
||||
setKey(DOWNLOAD_COUNT_KEY, (getKey(DOWNLOAD_COUNT_KEY) ?: 0) + 1)
|
||||
mainThread {
|
||||
showToast(
|
||||
activity,
|
||||
if (linksFound) R.string.download_started else R.string.no_links_found_toast,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun download(activity: Activity?, card: ResultEpisode) = ioSafe {
|
||||
getRequest(card)?.let { req ->
|
||||
downloadFromRequest(activity, req)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getRequest(card: ResultEpisode): DownloadRequest? {
|
||||
val response = currentResponse ?: return null
|
||||
return downloadEpisode(
|
||||
card,
|
||||
response.isMovie(),
|
||||
response.name,
|
||||
response.type,
|
||||
response.posterUrl,
|
||||
response.apiName,
|
||||
response.getId(),
|
||||
response.url
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun handleEpisodeClickEvent(activity: Activity?, click: EpisodeClickEvent) {
|
||||
when (click.action) {
|
||||
ACTION_SHOW_OPTIONS -> {
|
||||
|
@ -1117,18 +1236,11 @@ class ResultViewModel2 : ViewModel() {
|
|||
showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT)
|
||||
}
|
||||
ACTION_DOWNLOAD_EPISODE -> {
|
||||
val response = currentResponse ?: return
|
||||
downloadEpisode(
|
||||
activity,
|
||||
click.data,
|
||||
response.isMovie(),
|
||||
response.name,
|
||||
response.type,
|
||||
response.posterUrl,
|
||||
response.apiName,
|
||||
response.getId(),
|
||||
response.url
|
||||
)
|
||||
ioSafe {
|
||||
val response = currentResponse ?: return@ioSafe
|
||||
val req = getRequest(click.data) ?: return@ioSafe
|
||||
Aria2Starter.client?.downloadFailQueue(req.links) { _, _ -> }
|
||||
}
|
||||
}
|
||||
ACTION_DOWNLOAD_MIRROR -> {
|
||||
val response = currentResponse ?: return
|
||||
|
@ -1138,8 +1250,7 @@ class ResultViewModel2 : ViewModel() {
|
|||
txt(R.string.episode_action_download_mirror)
|
||||
) { (result, index) ->
|
||||
ioSafe {
|
||||
startDownload(
|
||||
activity,
|
||||
val req = getDownloadRequest(
|
||||
click.data,
|
||||
response.isMovie(),
|
||||
response.name,
|
||||
|
@ -1150,13 +1261,9 @@ class ResultViewModel2 : ViewModel() {
|
|||
response.url,
|
||||
listOf(result.links[index]),
|
||||
result.subs,
|
||||
)
|
||||
) ?: return@ioSafe
|
||||
downloadFromRequest(activity, req)
|
||||
}
|
||||
showToast(
|
||||
activity,
|
||||
R.string.download_started,
|
||||
Toast.LENGTH_SHORT
|
||||
)
|
||||
}
|
||||
}
|
||||
ACTION_RELOAD_EPISODE -> {
|
||||
|
@ -1592,7 +1699,8 @@ class ResultViewModel2 : ViewModel() {
|
|||
val idIndex = ep.key.id
|
||||
for ((index, i) in ep.value.withIndex()) {
|
||||
val episode = i.episode ?: (index + 1)
|
||||
val id = mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0)
|
||||
val id =
|
||||
mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0)
|
||||
if (!existingEpisodes.contains(id)) {
|
||||
existingEpisodes.add(id)
|
||||
val seasonData = loadResponse.seasonNames.getSeason(i.season)
|
||||
|
|
|
@ -22,15 +22,14 @@ import androidx.work.OneTimeWorkRequest
|
|||
import androidx.work.WorkManager
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.hippo.unifile.UniFile
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.MainActivity
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.services.VideoDownloadService
|
||||
import com.lagradost.cloudstream3.ui.download.Aria2cHelper
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
|
@ -426,7 +425,7 @@ object VideoDownloadManager {
|
|||
}
|
||||
|
||||
private const val reservedChars = "|\\?*<\":>+[]/\'"
|
||||
fun sanitizeFilename(name: String, removeSpaces: Boolean= false): String {
|
||||
fun sanitizeFilename(name: String, removeSpaces: Boolean = false): String {
|
||||
var tempName = name
|
||||
for (c in reservedChars) {
|
||||
tempName = tempName.replace(c, ' ')
|
||||
|
@ -531,6 +530,7 @@ object VideoDownloadManager {
|
|||
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
|
||||
projection, selection, null, null
|
||||
)
|
||||
println("result:$result ${result?.count}")
|
||||
|
||||
result.use { c ->
|
||||
if (c != null && c.count >= 1) {
|
||||
|
@ -941,7 +941,7 @@ object VideoDownloadManager {
|
|||
* @param directoryName if null will use the current path.
|
||||
* @return UniFile / null if createMissingDirectories = false and folder is not found.
|
||||
* */
|
||||
private fun UniFile.gotoDir(
|
||||
fun UniFile.gotoDir(
|
||||
directoryName: String?,
|
||||
createMissingDirectories: Boolean = true
|
||||
): UniFile? {
|
||||
|
@ -995,7 +995,7 @@ object VideoDownloadManager {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getDisplayName(name: String, extension: String): String {
|
||||
fun getDisplayName(name: String, extension: String): String {
|
||||
return "$name.$extension"
|
||||
}
|
||||
|
||||
|
@ -1487,27 +1487,50 @@ object VideoDownloadManager {
|
|||
|
||||
fun getDownloadFileInfoAndUpdateSettings(context: Context, id: Int): DownloadedFileInfoResult? {
|
||||
val res = getDownloadFileInfo(context, id)
|
||||
if (res == null) context.removeKey(KEY_DOWNLOAD_INFO, id.toString())
|
||||
if (res == null) {
|
||||
Aria2cHelper.getMetadata(id.toLong())?.let { data ->
|
||||
if (Aria2cHelper.downloadExist(data)) {
|
||||
return DownloadedFileInfoResult(
|
||||
data.downloadedLength,
|
||||
data.totalLength,
|
||||
Uri.EMPTY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Aria2cHelper.deleteId(id.toLong())
|
||||
context.removeKey(KEY_DOWNLOAD_INFO, id.toString())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? {
|
||||
try {
|
||||
println("getDownloadFileInfo:$id")
|
||||
|
||||
val info =
|
||||
context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return null
|
||||
val base = basePathToFile(context, info.basePath)
|
||||
|
||||
println("BASE:$info")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) {
|
||||
val cr = context.contentResolver ?: return null
|
||||
println("CR:$cr")
|
||||
|
||||
val fileUri =
|
||||
cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName)
|
||||
?: return null
|
||||
println("FILEURI:$fileUri")
|
||||
|
||||
val fileLength = cr.getFileLength(fileUri) ?: return null
|
||||
println("fileLength:$fileLength")
|
||||
|
||||
if (fileLength == 0L) return null
|
||||
return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri)
|
||||
} else {
|
||||
println("STUFF:$base")
|
||||
|
||||
val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName)
|
||||
println("file:$file")
|
||||
|
||||
// val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName)
|
||||
// val dFile = File(normalPath)
|
||||
|
@ -1612,12 +1635,12 @@ object VideoDownloadManager {
|
|||
.mapIndexed { index, any -> DownloadQueueResumePackage(index, any) }
|
||||
.toTypedArray()
|
||||
setKey(KEY_RESUME_QUEUE_PACKAGES, dQueue)
|
||||
} catch (t : Throwable) {
|
||||
} catch (t: Throwable) {
|
||||
logError(t)
|
||||
}
|
||||
}
|
||||
|
||||
/*fun isMyServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
|
||||
/*fun isMyServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
|
||||
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
|
||||
for (service in manager!!.getRunningServices(Int.MAX_VALUE)) {
|
||||
if (serviceClass.name == service.service.className) {
|
||||
|
@ -1625,7 +1648,7 @@ object VideoDownloadManager {
|
|||
}
|
||||
}
|
||||
return false
|
||||
}*/
|
||||
}*/
|
||||
|
||||
fun downloadEpisode(
|
||||
context: Context?,
|
||||
|
|
60
app/src/main/res/layout/download_button_layout.xml
Normal file
60
app/src/main/res/layout/download_button_layout.xml
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
style="@style/BlackButton"
|
||||
android:id="@+id/download_big_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center">
|
||||
|
||||
<include
|
||||
android:layout_gravity="center"
|
||||
layout="@layout/download_button_view"
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="35dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="Downloading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text_precentage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:text="68%"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -3,116 +3,93 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
||||
android:nextFocusRight="@id/download_child_episode_download"
|
||||
android:nextFocusLeft="@id/nav_rail_view"
|
||||
|
||||
android:id="@+id/download_child_episode_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
android:layout_height="50dp"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
app:cardElevation="0dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
android:layout_marginBottom="5dp">
|
||||
android:nextFocusLeft="@id/nav_rail_view"
|
||||
android:nextFocusRight="@id/download_child_episode_download"
|
||||
app:cardBackgroundColor="@color/transparent"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:id="@+id/download_child_episode_progress"
|
||||
|
||||
android:layout_marginBottom="-1.5dp"
|
||||
android:progressTint="?attr/colorPrimary"
|
||||
android:progressBackgroundTint="?attr/colorPrimary"
|
||||
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
tools:progress="50"
|
||||
android:layout_height="5dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_height="5dp" />
|
||||
android:layout_marginBottom="-1.5dp"
|
||||
android:progressBackgroundTint="?attr/colorPrimary"
|
||||
android:progressTint="?attr/colorPrimary"
|
||||
tools:progress="50" />
|
||||
|
||||
<GridLayout
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/download_child_episode_play"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:contentDescription="@string/episode_play_img_des"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/episode_play_img_des" />
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_width="match_parent">
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_child_episode_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1"
|
||||
|
||||
android:scrollHorizontally="true"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center_vertical"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:singleLine="true"
|
||||
android:scrollHorizontally="true"
|
||||
|
||||
android:singleLine="true"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_child_episode_text_extra"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="128MB / 237MB"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent" />
|
||||
tools:text="128MB / 237MB" />
|
||||
</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:id="@+id/download_child_episode_progress_downloaded"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
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:nextFocusRight="@id/download_child_episode_holder"
|
||||
android:nextFocusLeft="@id/download_child_episode_holder"
|
||||
|
||||
android:id="@+id/download_child_episode_download"
|
||||
android:visibility="visible"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="10dp"
|
||||
android:layout_width="50dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
app:tint="?attr/textColor"
|
||||
android:contentDescription="@string/download" />
|
||||
</FrameLayout>
|
||||
</GridLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end">
|
||||
|
||||
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
android:id="@+id/download_child_episode_download"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="10dp" />
|
||||
</FrameLayout>
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -2,21 +2,21 @@
|
|||
<androidx.cardview.widget.CardView 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:id="@+id/episode_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||
android:id="@+id/episode_holder"
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="10dp">
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||
|
||||
<LinearLayout
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:orientation="horizontal">
|
||||
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="70dp"
|
||||
|
@ -24,80 +24,43 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/download_header_poster"
|
||||
tools:src="@drawable/example_poster"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/episode_poster_img_des" />
|
||||
android:contentDescription="@string/episode_poster_img_des"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/example_poster" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginStart="15dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginEnd="70dp"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_header_title"
|
||||
tools:text="Perfect Run"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textStyle="bold"
|
||||
tools:text="Perfect Run" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download_header_info"
|
||||
tools:text="1 episode | 285MB"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_marginStart="-50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="50dp"
|
||||
android:layout_width="50dp"
|
||||
android:id="@+id/download_header_goto_child"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:src="@drawable/ic_baseline_keyboard_arrow_right_24"
|
||||
android:contentDescription="@string/download" />
|
||||
|
||||
<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/download_header_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="center_vertical"
|
||||
android:progress="0"
|
||||
android:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:visibility="visible"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp"
|
||||
android:layout_width="50dp"
|
||||
android:id="@+id/download_header_episode_download"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/download"
|
||||
app:tint="?attr/white" />
|
||||
</FrameLayout>
|
||||
android:textColor="?attr/grayTextColor"
|
||||
tools:text="1 episode | 285MB" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
android:id="@+id/download_header_download"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="10dp" />
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -569,90 +569,12 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent" />-->
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/result_movie_progress_downloaded_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
<com.lagradost.cloudstream3.ui.DownloadButton
|
||||
android:id="@+id/result_download_movie"
|
||||
style="@style/BlackButton"
|
||||
|
||||
android:layout_width="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
|
||||
android:nextFocusUp="@id/result_play_movie"
|
||||
android:nextFocusDown="@id/result_season_button"
|
||||
android:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:id="@+id/result_movie_progress_downloaded"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:background="@drawable/circle_shape"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:progress="30"
|
||||
android:progressDrawable="@drawable/circular_progress_bar_filled"
|
||||
android:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/result_movie_download_icon"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/download"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:visibility="visible"
|
||||
app:tint="?attr/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="Downloading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text_precentage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:text="68%" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
android:layout_gravity="center"
|
||||
app:aria2c_layout="@layout/download_button_layout" />
|
||||
|
||||
<!--<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -418,109 +418,25 @@
|
|||
|
||||
</com.google.android.material.button.MaterialButton>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:nextFocusRight="@id/result_bookmark_button"
|
||||
android:id="@+id/result_movie_progress_downloaded_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_weight="1"
|
||||
android:minWidth="250dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
<com.lagradost.cloudstream3.ui.DownloadButton
|
||||
android:id="@+id/result_download_movie"
|
||||
style="@style/BlackButton"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="0dp"
|
||||
|
||||
android:layout_marginEnd="0dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:nextFocusLeft="@id/result_play_movie"
|
||||
android:nextFocusUp="@id/result_cast_items"
|
||||
android:nextFocusDown="@id/result_resume_series_button_play"
|
||||
|
||||
android:visibility="visible" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:id="@+id/result_movie_progress_downloaded"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:layout_margin="5dp"
|
||||
android:background="@drawable/circle_shape"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:progress="30"
|
||||
android:progressDrawable="@drawable/circular_progress_bar_filled"
|
||||
android:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/result_movie_download_icon"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/download"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:visibility="visible"
|
||||
app:tint="?attr/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
tools:text="Downloading" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_movie_download_text_precentage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.09"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textSize="15sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:text="68%" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
android:layout_weight="1"
|
||||
android:minWidth="250dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:nextFocusLeft="@id/result_movie_progress_downloaded_holder"
|
||||
android:nextFocusDown="@id/result_resume_series_button_play"
|
||||
|
||||
android:id="@+id/result_bookmark_button"
|
||||
style="@style/BlackButton"
|
||||
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_weight="1"
|
||||
android:minWidth="250dp"
|
||||
android:nextFocusLeft="@id/result_download_movie"
|
||||
android:nextFocusDown="@id/result_resume_series_button_play"
|
||||
android:text="@string/type_none"
|
||||
android:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
|
|
@ -95,35 +95,13 @@
|
|||
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" />
|
||||
|
||||
<!--
|
||||
android:nextFocusRight="@id/episode_holder"-->
|
||||
<ImageView
|
||||
android:nextFocusLeft="@id/episode_holder"
|
||||
app:tint="?attr/white"
|
||||
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:id="@+id/result_episode_download"
|
||||
android:visibility="visible"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_gravity="center"
|
||||
android:padding="10dp"
|
||||
android:layout_width="50dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/download" />
|
||||
android:layout_height="50dp">
|
||||
</com.lagradost.fetchbutton.ui.PieFetchButton>
|
||||
</FrameLayout>
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -3,27 +3,27 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
||||
android:nextFocusRight="@id/result_episode_download"
|
||||
android:id="@+id/episode_holder_large"
|
||||
|
||||
android:layout_width="match_parent"
|
||||
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:nextFocusRight="@id/result_episode_download"
|
||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||
|
||||
android:layout_marginBottom="10dp">
|
||||
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:padding="10dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:padding="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="126dp"
|
||||
|
@ -31,121 +31,100 @@
|
|||
android:foreground="@drawable/outline_drawable">
|
||||
|
||||
<ImageView
|
||||
android:nextFocusRight="@id/result_episode_download"
|
||||
|
||||
android:id="@+id/episode_poster"
|
||||
tools:src="@drawable/example_poster"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/episode_poster_img_des" />
|
||||
android:contentDescription="@string/episode_poster_img_des"
|
||||
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:nextFocusRight="@id/result_episode_download"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/example_poster" />
|
||||
|
||||
<ImageView
|
||||
android:src="@drawable/play_button"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:contentDescription="@string/play_episode" />
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/play_episode"
|
||||
android:src="@drawable/play_button" />
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
android:layout_marginBottom="-1.5dp"
|
||||
android:id="@+id/episode_progress"
|
||||
android:progressTint="?attr/colorPrimary"
|
||||
android:progressBackgroundTint="?attr/colorPrimary"
|
||||
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
tools:progress="50"
|
||||
android:layout_height="5dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_height="5dp" />
|
||||
android:layout_marginBottom="-1.5dp"
|
||||
android:progressBackgroundTint="?attr/colorPrimary"
|
||||
android:progressTint="?attr/colorPrimary"
|
||||
tools:progress="50" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginStart="15dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_height="wrap_content">
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:layout_gravity="start"
|
||||
android:id="@+id/episode_filler"
|
||||
style="@style/SmallBlackButton"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/filler"
|
||||
android:id="@+id/episode_filler" />
|
||||
android:text="@string/filler" />
|
||||
|
||||
<TextView
|
||||
android:layout_gravity="center_vertical"
|
||||
android:id="@+id/episode_text"
|
||||
tools:text="1. Jobless"
|
||||
android:textStyle="bold"
|
||||
android:textColor="?attr/textColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textColor="?attr/textColor"
|
||||
android:textStyle="bold"
|
||||
tools:text="1. Jobless" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/episode_rating"
|
||||
tools:text="Rated: 8.8"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
tools:text="Rated: 8.8" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_marginStart="-50dp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginStart="-50dp">
|
||||
|
||||
<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:nextFocusLeft="@id/episode_poster"
|
||||
android:id="@+id/result_episode_download"
|
||||
|
||||
android:visibility="visible"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:padding="10dp"
|
||||
android:layout_width="50dp"
|
||||
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
||||
android:contentDescription="@string/download"
|
||||
app:tint="?attr/white" />
|
||||
android:id="@+id/result_episode_download"
|
||||
android:layout_gravity="center"
|
||||
android:padding="5dp"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp">
|
||||
</com.lagradost.fetchbutton.ui.PieFetchButton>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:maxLines="4"
|
||||
android:id="@+id/episode_descript"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="4"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:id="@+id/episode_descript"
|
||||
android:textColor="?attr/grayTextColor"
|
||||
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart."
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart." />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
|
@ -22,6 +22,10 @@
|
|||
<color name="white">#FFF</color>
|
||||
<color name="black">#000</color>
|
||||
|
||||
<color name="whiteText">#FFF</color>
|
||||
<color name="blackText">#000</color>
|
||||
|
||||
|
||||
<color name="dubColor">#3d50fa</color> <!--3b65f5 f18c82 8294F1-->
|
||||
<color name="amoledModeLight">#121213</color>
|
||||
|
||||
|
|
|
@ -49,11 +49,14 @@
|
|||
|
||||
<item name="android:windowAllowReturnTransitionOverlap">true</item>
|
||||
<item name="android:windowAllowEnterTransitionOverlap">true</item>
|
||||
|
||||
<!--<item name="preferenceTheme">@style/PreferencesTheme</item>-->
|
||||
|
||||
<!-- DEF STYLE -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="textColor">@color/textColor</item>
|
||||
<item name="grayTextColor">@color/grayTextColor</item>
|
||||
|
@ -65,6 +68,10 @@
|
|||
<item name="white">#FFF</item>
|
||||
|
||||
<item name="preferenceTheme">@style/CustomPreferenceThemeOverlay</item>
|
||||
<item name="aria2c_icon_color">?attr/white</item>
|
||||
<item name="aria2c_fill_color">?attr/white</item>
|
||||
<item name="aria2c_outline_color">?attr/white</item>
|
||||
<item name="aria2c_icon_scale">0.7</item>
|
||||
</style>
|
||||
|
||||
<style name="ListViewStyle" parent="Widget.AppCompat.ListView">
|
||||
|
@ -100,7 +107,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="colorOnPrimary">@color/colorAccent</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
@ -110,7 +117,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryBlue</item>
|
||||
<item name="colorPrimaryDark">#4855A2</item>
|
||||
<item name="colorAccent">#5A6BCB</item>
|
||||
<item name="colorOnPrimary">#5A6BCB</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryBlue</item>
|
||||
</style>
|
||||
|
@ -120,7 +127,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryPurple</item>
|
||||
<item name="colorPrimaryDark">#4704A3</item>
|
||||
<item name="colorAccent">#7125DB</item>
|
||||
<item name="colorOnPrimary">#7125DB</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryPurple</item>
|
||||
</style>
|
||||
|
||||
|
@ -129,7 +136,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryGreen</item>
|
||||
<item name="colorPrimaryDark">#007363</item>
|
||||
<item name="colorAccent">#39C1AE</item>
|
||||
<item name="colorOnPrimary">#39C1AE</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryGreen</item>
|
||||
</style>
|
||||
|
||||
|
@ -138,7 +145,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryGreenApple</item>
|
||||
<item name="colorPrimaryDark">#319B5A</item>
|
||||
<item name="colorAccent">#51C57E</item>
|
||||
<item name="colorOnPrimary">#51C57E</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryGreenApple</item>
|
||||
</style>
|
||||
|
||||
|
@ -147,7 +154,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryRed</item>
|
||||
<item name="colorPrimaryDark">#B62B2B</item>
|
||||
<item name="colorAccent">@color/colorPrimaryRed</item> <!--#F53B3B-->
|
||||
<item name="colorOnPrimary">@color/colorPrimaryRed</item> <!--#EC3838-->
|
||||
<item name="colorOnPrimary">@color/whiteText</item> <!--#EC3838-->
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryRed</item>
|
||||
</style>
|
||||
|
@ -157,7 +164,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryBanana</item>
|
||||
<item name="colorPrimaryDark">#9B7D31</item>
|
||||
<item name="colorAccent">#C5B251</item>
|
||||
<item name="colorOnPrimary">#C5A851</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryBanana</item>
|
||||
</style>
|
||||
|
||||
|
@ -166,7 +173,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryParty</item>
|
||||
<item name="colorPrimaryDark">#C1495B</item>
|
||||
<item name="colorAccent">#FD798C</item>
|
||||
<item name="colorOnPrimary">#BF5968</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryParty</item>
|
||||
</style>
|
||||
|
||||
|
@ -175,7 +182,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryPink</item>
|
||||
<item name="colorPrimaryDark">#DD1280</item>
|
||||
<item name="colorAccent">#FF4DAE</item>
|
||||
<item name="colorOnPrimary">#DD1280</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<item name="android:colorAccent">@color/colorPrimaryPink</item>
|
||||
</style>
|
||||
|
||||
|
@ -184,7 +191,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryCarnationPink</item>
|
||||
<item name="colorPrimaryDark">#83366f</item>
|
||||
<item name="colorAccent">#BD5DA5</item>
|
||||
<item name="colorOnPrimary">#BD5DA5</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryCarnationPink</item>
|
||||
</style>
|
||||
|
@ -194,7 +201,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryMaroon</item>
|
||||
<item name="colorPrimaryDark">#370C0C</item>
|
||||
<item name="colorAccent">#451010</item>
|
||||
<item name="colorOnPrimary">#451010</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryMaroon</item>
|
||||
</style>
|
||||
|
@ -204,7 +211,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryDarkGreen</item>
|
||||
<item name="colorPrimaryDark">#003d00</item>
|
||||
<item name="colorAccent">#004500</item>
|
||||
<item name="colorOnPrimary">#004500</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryDarkGreen</item>
|
||||
</style>
|
||||
|
@ -214,7 +221,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryNavyBlue</item>
|
||||
<item name="colorPrimaryDark">#000073</item>
|
||||
<item name="colorAccent">#000080</item>
|
||||
<item name="colorOnPrimary">#000080</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryNavyBlue</item>
|
||||
</style>
|
||||
|
@ -224,7 +231,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryGrey</item>
|
||||
<item name="colorPrimaryDark">#484848</item>
|
||||
<item name="colorAccent">#515151</item>
|
||||
<item name="colorOnPrimary">#515151</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryGrey</item>
|
||||
</style>
|
||||
|
@ -234,7 +241,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryWhite</item>
|
||||
<item name="colorPrimaryDark">#CCCCCC</item>
|
||||
<item name="colorAccent">#FFFFFF</item>
|
||||
<item name="colorOnPrimary">#FFFFFF</item>
|
||||
<item name="colorOnPrimary">@color/blackText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryWhite</item>
|
||||
</style>
|
||||
|
@ -244,7 +251,7 @@
|
|||
<item name="android:colorPrimary">@color/colorPrimaryBrown</item>
|
||||
<item name="colorPrimaryDark">#582700</item>
|
||||
<item name="colorAccent">#622C00</item>
|
||||
<item name="colorOnPrimary">#622C00</item>
|
||||
<item name="colorOnPrimary">@color/whiteText</item>
|
||||
<!-- Needed for leanback fuckery -->
|
||||
<item name="android:colorAccent">@color/colorPrimaryBrown</item>
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue