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
|
// Library/extensions searching with Levenshtein distance
|
||||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||||
|
|
||||||
|
// aria2c downloader
|
||||||
|
implementation 'com.github.LagradOst:Aria2cButton:v0.0.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
task androidSourcesJar(type: Jar) {
|
task androidSourcesJar(type: Jar) {
|
||||||
|
|
|
@ -17,6 +17,8 @@ import androidx.appcompat.widget.SearchView
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.gms.cast.framework.CastSession
|
import com.google.android.gms.cast.framework.CastSession
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
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.player.PlayerEventType
|
||||||
import com.lagradost.cloudstream3.ui.result.UiText
|
import com.lagradost.cloudstream3.ui.result.UiText
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateTv
|
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.hasPIPPermission
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
|
import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
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 org.schabi.newpipe.extractor.NewPipe
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
object CommonActivity {
|
object CommonActivity {
|
||||||
@MainThread
|
@MainThread
|
||||||
|
@ -129,6 +136,43 @@ object CommonActivity {
|
||||||
act.updateLocale()
|
act.updateLocale()
|
||||||
act.updateTv()
|
act.updateTv()
|
||||||
NewPipe.init(DownloaderTestImpl.getInstance())
|
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() {
|
private fun Activity.enterPIPMode() {
|
||||||
|
|
|
@ -10,10 +10,10 @@ import android.view.KeyEvent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.navigation.NavController
|
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_EXTRA_DURATION_OUT = "extra_duration"
|
||||||
const val VLC_LAST_ID_KEY = "vlc_last_open_id"
|
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
|
// Short name for requests client to make it nicer to use
|
||||||
|
|
||||||
var app = Requests(responseParser = object : ResponseParser {
|
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)
|
* @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.
|
* @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) {
|
with(activity) {
|
||||||
if (str != null && this != null) {
|
if (str != null && this != null) {
|
||||||
if (str.startsWith("https://cs.repo")) {
|
if (str.startsWith("https://cs.repo")) {
|
||||||
|
@ -191,7 +197,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
val url = str.replaceFirst(appStringRepo, "https")
|
val url = str.replaceFirst(appStringRepo, "https")
|
||||||
loadRepository(url)
|
loadRepository(url)
|
||||||
return true
|
return true
|
||||||
} else if (!isWebview){
|
} else if (!isWebview) {
|
||||||
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
||||||
this.navigate(R.id.navigation_downloads)
|
this.navigate(R.id.navigation_downloads)
|
||||||
return true
|
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_view?.isVisible = isNavVisible && !landscape
|
||||||
nav_rail_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.app.Activity
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.text.format.Formatter
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
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.AcraApplication.Companion.getKey
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator
|
||||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
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.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorUri
|
import com.lagradost.cloudstream3.utils.ExtractorUri
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
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.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
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 {
|
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) {
|
fun handleDownloadClick(activity: Activity?, click: DownloadClickEvent) {
|
||||||
val id = click.data.id
|
val id = click.data.id
|
||||||
if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return
|
if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return
|
||||||
|
@ -29,6 +167,7 @@ object DownloadButtonSetup {
|
||||||
DialogInterface.OnClickListener { _, which ->
|
DialogInterface.OnClickListener { _, which ->
|
||||||
when (which) {
|
when (which) {
|
||||||
DialogInterface.BUTTON_POSITIVE -> {
|
DialogInterface.BUTTON_POSITIVE -> {
|
||||||
|
Aria2cHelper.deleteId(id.toLong())
|
||||||
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
VideoDownloadManager.deleteFileAndUpdateSettings(ctx, id)
|
||||||
}
|
}
|
||||||
DialogInterface.BUTTON_NEGATIVE -> {
|
DialogInterface.BUTTON_NEGATIVE -> {
|
||||||
|
@ -57,11 +196,14 @@ object DownloadButtonSetup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
DOWNLOAD_ACTION_PAUSE_DOWNLOAD -> {
|
||||||
|
Aria2cHelper.pause(click.data.id.toLong())
|
||||||
VideoDownloadManager.downloadEvent.invoke(
|
VideoDownloadManager.downloadEvent.invoke(
|
||||||
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
Pair(click.data.id, VideoDownloadManager.DownloadActionType.Pause)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
DOWNLOAD_ACTION_RESUME_DOWNLOAD -> {
|
||||||
|
Aria2cHelper.unpause(click.data.id.toLong())
|
||||||
|
|
||||||
activity?.let { ctx ->
|
activity?.let { ctx ->
|
||||||
if (VideoDownloadManager.downloadStatus.containsKey(id) && VideoDownloadManager.downloadStatus[id] == VideoDownloadManager.DownloadType.IsPaused) {
|
if (VideoDownloadManager.downloadStatus.containsKey(id) && VideoDownloadManager.downloadStatus[id] == VideoDownloadManager.DownloadType.IsPaused) {
|
||||||
VideoDownloadManager.downloadEvent.invoke(
|
VideoDownloadManager.downloadEvent.invoke(
|
||||||
|
@ -86,6 +228,7 @@ object DownloadButtonSetup {
|
||||||
act,
|
act,
|
||||||
click.data.id
|
click.data.id
|
||||||
)?.fileLength
|
)?.fileLength
|
||||||
|
?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength
|
||||||
?: 0
|
?: 0
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
showToast(act, R.string.delete, Toast.LENGTH_LONG)
|
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.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
|
import com.lagradost.cloudstream3.ui.result.DownloadHelper.play
|
||||||
|
import com.lagradost.cloudstream3.ui.result.ResultEpisode
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
import kotlinx.android.synthetic.main.download_child_episode.view.*
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
const val DOWNLOAD_ACTION_PLAY_FILE = 0
|
||||||
const val DOWNLOAD_ACTION_DELETE_FILE = 1
|
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_DOWNLOAD = 4
|
||||||
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
const val DOWNLOAD_ACTION_LONG_CLICK = 5
|
||||||
|
|
||||||
|
interface IVisualDownloadChildCached{
|
||||||
|
val currentBytes: Long
|
||||||
|
val totalBytes: Long
|
||||||
|
val data: VideoDownloadHelper.DownloadEpisodeCached?
|
||||||
|
}
|
||||||
|
|
||||||
data class VisualDownloadChildCached(
|
data class VisualDownloadChildCached(
|
||||||
val currentBytes: Long,
|
override val currentBytes: Long,
|
||||||
val totalBytes: Long,
|
override val totalBytes: Long,
|
||||||
val data: VideoDownloadHelper.DownloadEpisodeCached,
|
override val data: VideoDownloadHelper.DownloadEpisodeCached,
|
||||||
)
|
) : IVisualDownloadChildCached
|
||||||
|
|
||||||
data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData)
|
data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData)
|
||||||
|
data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||||
|
|
||||||
class DownloadChildAdapter(
|
class DownloadChildAdapter(
|
||||||
var cardList: List<VisualDownloadChildCached>,
|
var cardList: List<VisualDownloadChildCached>,
|
||||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
private val clickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : 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 {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return DownloadChildViewHolder(
|
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
|
clickCallback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +58,6 @@ class DownloadChildAdapter(
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is DownloadChildViewHolder -> {
|
is DownloadChildViewHolder -> {
|
||||||
holder.bind(cardList[position])
|
holder.bind(cardList[position])
|
||||||
mBoundViewHolders.add(holder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,15 +70,13 @@ class DownloadChildAdapter(
|
||||||
constructor(
|
constructor(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val clickCallback: (DownloadClickEvent) -> Unit,
|
private val clickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
override var downloadButton = EasyDownloadButton()
|
|
||||||
|
|
||||||
private val title: TextView = itemView.download_child_episode_text
|
private val title: TextView = itemView.download_child_episode_text
|
||||||
private val extraInfo: TextView = itemView.download_child_episode_text_extra
|
private val extraInfo: TextView = itemView.download_child_episode_text_extra
|
||||||
private val holder: CardView = itemView.download_child_episode_holder
|
private val holder: CardView = itemView.download_child_episode_holder
|
||||||
private val progressBar: ContentLoadingProgressBar = itemView.download_child_episode_progress
|
private val progressBar: ContentLoadingProgressBar =
|
||||||
private val progressBarDownload: ContentLoadingProgressBar = itemView.download_child_episode_progress_downloaded
|
itemView.download_child_episode_progress
|
||||||
private val downloadImage: ImageView = itemView.download_child_episode_download
|
private val downloadButton: PieFetchButton = itemView.download_child_episode_download
|
||||||
|
|
||||||
private var localCard: VisualDownloadChildCached? = null
|
private var localCard: VisualDownloadChildCached? = null
|
||||||
|
|
||||||
|
@ -118,35 +96,17 @@ class DownloadChildAdapter(
|
||||||
|
|
||||||
title.text = title.context.getNameFull(d.name, d.episode, d.season)
|
title.text = title.context.getNameFull(d.name, d.episode, d.season)
|
||||||
title.isSelected = true // is needed for text repeating
|
title.isSelected = true // is needed for text repeating
|
||||||
|
//extraInfo.text = card.currentBytes
|
||||||
downloadButton.setUpButton(
|
DownloadButtonSetup.bind(card, downloadButton, extraInfo, clickCallback)
|
||||||
card.currentBytes,
|
|
||||||
card.totalBytes,
|
|
||||||
progressBarDownload,
|
|
||||||
downloadImage,
|
|
||||||
extraInfo,
|
|
||||||
card.data,
|
|
||||||
clickCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
if (downloadButton.isVisible) {
|
||||||
}
|
downloadButton.play(d)
|
||||||
}
|
} else {
|
||||||
|
holder.setOnClickListener {
|
||||||
override fun reattachDownloadButton() {
|
clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, d))
|
||||||
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.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
import com.lagradost.cloudstream3.utils.DataStore.getKeys
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
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.VideoDownloadHelper
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||||
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
import kotlinx.android.synthetic.main.fragment_child_downloads.*
|
||||||
|
@ -21,7 +22,7 @@ import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class DownloadChildFragment : Fragment() {
|
class DownloadChildFragment : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(headerName: String, folder: String) : Bundle {
|
fun newInstance(headerName: String, folder: String): Bundle {
|
||||||
return Bundle().apply {
|
return Bundle().apply {
|
||||||
putString("folder", folder)
|
putString("folder", folder)
|
||||||
putString("name", headerName)
|
putString("name", headerName)
|
||||||
|
@ -30,15 +31,18 @@ class DownloadChildFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
(download_child_list?.adapter as DownloadChildAdapter?)?.killAdapter()
|
|
||||||
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
|
downloadDeleteEventListener?.let { VideoDownloadManager.downloadDeleteEvent -= it }
|
||||||
super.onDestroyView()
|
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)
|
return inflater.inflate(R.layout.fragment_child_downloads, container, false)
|
||||||
}
|
}
|
||||||
|
private var hasPopped = false // fix stupid bug
|
||||||
private fun updateList(folder: String) = main {
|
private fun updateList(folder: String) = main {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) }
|
||||||
|
@ -50,9 +54,11 @@ class DownloadChildFragment : Fragment() {
|
||||||
?: return@mapNotNull null
|
?: return@mapNotNull null
|
||||||
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
VisualDownloadChildCached(info.fileLength, info.totalBytes, it)
|
||||||
}
|
}
|
||||||
}.sortedBy { it.data.episode + (it.data.season?: 0)*100000 }
|
}.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 }
|
||||||
if (eps.isEmpty()) {
|
|
||||||
activity?.onBackPressed()
|
if (eps.isEmpty() && !hasPopped) {
|
||||||
|
hasPopped = true
|
||||||
|
activity?.popCurrentPage()
|
||||||
return@main
|
return@main
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +91,13 @@ class DownloadChildFragment : Fragment() {
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
) { click ->
|
) { click ->
|
||||||
handleDownloadClick(activity, 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 ->
|
downloadDeleteEventListener = { id: Int ->
|
||||||
|
|
|
@ -69,7 +69,6 @@ class DownloadFragment : Fragment() {
|
||||||
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!!
|
||||||
downloadDeleteEventListener = null
|
downloadDeleteEventListener = null
|
||||||
}
|
}
|
||||||
(download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter()
|
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +164,7 @@ class DownloadFragment : Fragment() {
|
||||||
downloadDeleteEventListener = { id ->
|
downloadDeleteEventListener = { id ->
|
||||||
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList
|
||||||
if (list != null) {
|
if (list != null) {
|
||||||
if (list.any { it.data.id == id }) {
|
if (list.any { it.data?.id == id }) {
|
||||||
context?.let { ctx ->
|
context?.let { ctx ->
|
||||||
setList(ArrayList())
|
setList(ArrayList())
|
||||||
downloadsViewModel.updateList(ctx)
|
downloadsViewModel.updateList(ctx)
|
||||||
|
|
|
@ -8,23 +8,25 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.ContentLoadingProgressBar
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
import com.lagradost.cloudstream3.utils.VideoDownloadHelper
|
||||||
|
import com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
import kotlinx.android.synthetic.main.download_header_episode.view.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
data class VisualDownloadHeaderCached(
|
data class VisualDownloadHeaderCached(
|
||||||
val currentOngoingDownloads: Int,
|
val currentOngoingDownloads: Int,
|
||||||
val totalDownloads: Int,
|
val totalDownloads: Int,
|
||||||
val totalBytes: Long,
|
override val totalBytes: Long,
|
||||||
val currentBytes: Long,
|
override val currentBytes: Long,
|
||||||
val data: VideoDownloadHelper.DownloadHeaderCached,
|
val header: VideoDownloadHelper.DownloadHeaderCached,
|
||||||
val child: VideoDownloadHelper.DownloadEpisodeCached?,
|
override val data: VideoDownloadHelper.DownloadEpisodeCached?,
|
||||||
)
|
) : IVisualDownloadChildCached
|
||||||
|
|
||||||
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached)
|
||||||
|
|
||||||
|
@ -34,35 +36,6 @@ class DownloadHeaderAdapter(
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : 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 {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
return DownloadHeaderViewHolder(
|
return DownloadHeaderViewHolder(
|
||||||
|
@ -76,7 +49,6 @@ class DownloadHeaderAdapter(
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is DownloadHeaderViewHolder -> {
|
is DownloadHeaderViewHolder -> {
|
||||||
holder.bind(cardList[position])
|
holder.bind(cardList[position])
|
||||||
mBoundViewHolders.add(holder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,23 +62,17 @@ class DownloadHeaderAdapter(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
private val clickCallback: (DownloadHeaderClickEvent) -> Unit,
|
||||||
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
private val movieClickCallback: (DownloadClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
override var downloadButton = EasyDownloadButton()
|
|
||||||
|
|
||||||
private val poster: ImageView? = itemView.download_header_poster
|
private val poster: ImageView? = itemView.download_header_poster
|
||||||
private val title: TextView = itemView.download_header_title
|
private val title: TextView = itemView.download_header_title
|
||||||
private val extraInfo: TextView = itemView.download_header_info
|
private val extraInfo: TextView = itemView.download_header_info
|
||||||
private val holder: CardView = itemView.episode_holder
|
private val holder: CardView = itemView.episode_holder
|
||||||
|
|
||||||
private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded
|
private val downloadButton: PieFetchButton = itemView.download_header_download
|
||||||
private val downloadImage: ImageView = itemView.download_header_episode_download
|
|
||||||
private val normalImage: ImageView = itemView.download_header_goto_child
|
|
||||||
private var localCard: VisualDownloadHeaderCached? = null
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: VisualDownloadHeaderCached) {
|
fun bind(card: VisualDownloadHeaderCached) {
|
||||||
localCard = card
|
val d = card.header
|
||||||
val d = card.data
|
|
||||||
|
|
||||||
poster?.setImage(d.poster)
|
poster?.setImage(d.poster)
|
||||||
poster?.setOnClickListener {
|
poster?.setOnClickListener {
|
||||||
|
@ -117,10 +83,8 @@ class DownloadHeaderAdapter(
|
||||||
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
val mbString = formatShortFileSize(itemView.context, card.totalBytes)
|
||||||
|
|
||||||
//val isMovie = d.type.isMovieType()
|
//val isMovie = d.type.isMovieType()
|
||||||
if (card.child != null) {
|
if (card.data != null) {
|
||||||
downloadBar.visibility = View.VISIBLE
|
downloadButton.isVisible = true
|
||||||
downloadImage.visibility = View.VISIBLE
|
|
||||||
normalImage.visibility = View.GONE
|
|
||||||
/*setUpButton(
|
/*setUpButton(
|
||||||
card.currentBytes,
|
card.currentBytes,
|
||||||
card.totalBytes,
|
card.totalBytes,
|
||||||
|
@ -130,14 +94,15 @@ class DownloadHeaderAdapter(
|
||||||
card.child,
|
card.child,
|
||||||
movieClickCallback
|
movieClickCallback
|
||||||
)*/
|
)*/
|
||||||
|
DownloadButtonSetup.bind(card, downloadButton, extraInfo) { click ->
|
||||||
|
movieClickCallback.invoke(DownloadClickEvent(click.action, card.data))
|
||||||
|
}
|
||||||
|
|
||||||
holder.setOnClickListener {
|
holder.setOnClickListener {
|
||||||
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child))
|
movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.data))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
downloadBar.visibility = View.GONE
|
downloadButton.isVisible = false
|
||||||
downloadImage.visibility = View.GONE
|
|
||||||
normalImage.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
extraInfo.text =
|
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
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.StatFs
|
import android.os.StatFs
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
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.isMovieType
|
||||||
import com.lagradost.cloudstream3.mvvm.launchSafe
|
import com.lagradost.cloudstream3.mvvm.launchSafe
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
@ -46,6 +49,8 @@ class DownloadViewModel : ViewModel() {
|
||||||
.distinctBy { it.id } // Remove duplicates
|
.distinctBy { it.id } // Remove duplicates
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("CHILDRE:$children")
|
||||||
|
|
||||||
// parentId : bytes
|
// parentId : bytes
|
||||||
val totalBytesUsedByChild = HashMap<Int, Long>()
|
val totalBytesUsedByChild = HashMap<Int, Long>()
|
||||||
// parentId : bytes
|
// parentId : bytes
|
||||||
|
@ -53,12 +58,10 @@ class DownloadViewModel : ViewModel() {
|
||||||
// parentId : downloadsCount
|
// parentId : downloadsCount
|
||||||
val totalDownloads = HashMap<Int, Int>()
|
val totalDownloads = HashMap<Int, Int>()
|
||||||
|
|
||||||
|
|
||||||
// Gets all children downloads
|
// Gets all children downloads
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
for (c in children) {
|
for (c in children) {
|
||||||
val childFile = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, c.id) ?: continue
|
val childFile = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(context, c.id) ?: continue
|
||||||
|
|
||||||
if (childFile.fileLength <= 1) continue
|
if (childFile.fileLength <= 1) continue
|
||||||
val len = childFile.totalBytes
|
val len = childFile.totalBytes
|
||||||
val flen = childFile.fileLength
|
val flen = childFile.fileLength
|
||||||
|
@ -68,7 +71,8 @@ class DownloadViewModel : ViewModel() {
|
||||||
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println("TotalDownloads:$totalDownloads")
|
||||||
|
//println("FIXED: $totalDownloads")
|
||||||
val cached = withContext(Dispatchers.IO) { // wont fetch useless keys
|
val cached = withContext(Dispatchers.IO) { // wont fetch useless keys
|
||||||
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
totalDownloads.entries.filter { it.value > 0 }.mapNotNull {
|
||||||
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
context.getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
||||||
|
@ -77,6 +81,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println("Cached:$cached")
|
||||||
|
|
||||||
val visual = withContext(Dispatchers.IO) {
|
val visual = withContext(Dispatchers.IO) {
|
||||||
cached.mapNotNull { // TODO FIX
|
cached.mapNotNull { // TODO FIX
|
||||||
|
@ -99,7 +104,7 @@ class DownloadViewModel : ViewModel() {
|
||||||
movieEpisode
|
movieEpisode
|
||||||
)
|
)
|
||||||
}.sortedBy {
|
}.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
|
} // episode sorting by episode, lowest to highest
|
||||||
}
|
}
|
||||||
try {
|
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 androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.lagradost.cloudstream3.R
|
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.DownloadButtonViewHolder
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadClickEvent
|
import com.lagradost.cloudstream3.ui.download.DownloadEpisodeClickEvent
|
||||||
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
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.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
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.*
|
||||||
import kotlinx.android.synthetic.main.result_episode.view.episode_text
|
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_filler
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.episode_progress
|
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_tv.view.*
|
||||||
import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_progress_downloaded
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||||
const val ACTION_PLAY_EPISODE_IN_VLC_PLAYER = 2
|
const val ACTION_PLAY_EPISODE_IN_VLC_PLAYER = 2
|
||||||
|
@ -58,21 +52,10 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||||
class EpisodeAdapter(
|
class EpisodeAdapter(
|
||||||
private val hasDownloadSupport: Boolean,
|
private val hasDownloadSupport: Boolean,
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit,
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
private var cardList: MutableList<ResultEpisode> = mutableListOf()
|
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) {
|
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||||
if (holder.itemView.hasFocus()) {
|
if (holder.itemView.hasFocus()) {
|
||||||
holder.itemView.clearFocus()
|
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) {
|
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
|
||||||
if (holder is DownloadButtonViewHolder) {
|
if (holder is DownloadButtonViewHolder) {
|
||||||
//println("onViewAttachedToWindow = ${holder.absoluteAdapterPosition}")
|
//println("onViewAttachedToWindow = ${holder.absoluteAdapterPosition}")
|
||||||
|
@ -138,7 +112,6 @@ class EpisodeAdapter(
|
||||||
when (holder) {
|
when (holder) {
|
||||||
is EpisodeCardViewHolder -> {
|
is EpisodeCardViewHolder -> {
|
||||||
holder.bind(cardList[position])
|
holder.bind(cardList[position])
|
||||||
mBoundViewHolders.add(holder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,18 +125,12 @@ class EpisodeAdapter(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val hasDownloadSupport: Boolean,
|
private val hasDownloadSupport: Boolean,
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
private val downloadClickCallback: (DownloadClickEvent) -> Unit,
|
private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
override var downloadButton = EasyDownloadButton()
|
//override var downloadButton = EasyDownloadButton()
|
||||||
|
|
||||||
var episodeDownloadBar: ContentLoadingProgressBar? = null
|
|
||||||
var episodeDownloadImage: ImageView? = null
|
|
||||||
var localCard: ResultEpisode? = null
|
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: ResultEpisode) {
|
fun bind(card: ResultEpisode) {
|
||||||
localCard = card
|
|
||||||
|
|
||||||
val isTrueTv = isTrueTvSettings()
|
val isTrueTv = isTrueTvSettings()
|
||||||
|
|
||||||
val (parentView, otherView) = if (card.poster == null) {
|
val (parentView, otherView) = if (card.poster == null) {
|
||||||
|
@ -181,9 +148,10 @@ class EpisodeAdapter(
|
||||||
val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress
|
val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress
|
||||||
val episodePoster: ImageView? = parentView.episode_poster
|
val episodePoster: ImageView? = parentView.episode_poster
|
||||||
|
|
||||||
episodeDownloadBar =
|
val downloadButton = parentView.result_episode_download
|
||||||
parentView.result_episode_progress_downloaded
|
|
||||||
episodeDownloadImage = parentView.result_episode_download
|
downloadButton.isVisible = hasDownloadSupport
|
||||||
|
downloadButton.setUp(card, downloadClickCallback)
|
||||||
|
|
||||||
val name =
|
val name =
|
||||||
if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.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
|
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.syncproviders.providers.Kitsu
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD
|
||||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_LONG_CLICK
|
||||||
import com.lagradost.cloudstream3.ui.download.EasyDownloadButton
|
|
||||||
import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment
|
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.isTrueTvSettings
|
||||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
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.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
import com.lagradost.cloudstream3.utils.AppUtils.html
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
|
import com.lagradost.cloudstream3.utils.AppUtils.openBrowser
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe
|
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
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.SingleSelectionHelper.showBottomDialog
|
||||||
|
import com.lagradost.cloudstream3.utils.UIHelper
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar
|
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_site
|
||||||
import kotlinx.android.synthetic.main.fragment_result.result_meta_type
|
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_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
|
||||||
import kotlinx.android.synthetic.main.fragment_result.result_next_airing_time
|
import kotlinx.android.synthetic.main.fragment_result.result_next_airing_time
|
||||||
import kotlinx.android.synthetic.main.fragment_result.result_no_episodes
|
import kotlinx.android.synthetic.main.fragment_result.result_no_episodes
|
||||||
|
@ -253,11 +248,8 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
return inflater.inflate(resultLayout, container, false)
|
return inflater.inflate(resultLayout, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var downloadButton: EasyDownloadButton? = null
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
updateUIListener = null
|
updateUIListener = null
|
||||||
(result_episodes?.adapter as EpisodeAdapter?)?.killAdapter()
|
|
||||||
downloadButton?.dispose()
|
|
||||||
|
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
@ -344,7 +336,18 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
return@setOnLongClickListener true
|
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 =
|
val file =
|
||||||
ioWorkSafe {
|
ioWorkSafe {
|
||||||
context?.let {
|
context?.let {
|
||||||
|
@ -389,11 +392,12 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result_movie_progress_downloaded_holder?.isVisible = true
|
result_movie_progress_downloaded_holder?.isVisible = true
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
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
|
result_play_movie?.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +462,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
val storedData = getStoredData(activity ?: context ?: return) ?: return
|
val storedData = getStoredData(activity ?: context ?: return) ?: return
|
||||||
|
|
||||||
//viewModel.clear()
|
//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 ->
|
{ episodeClick ->
|
||||||
viewModel.handleAction(activity, episodeClick)
|
viewModel.handleAction(activity, episodeClick)
|
||||||
},
|
},
|
||||||
{ downloadClickEvent ->
|
{ clickEvent ->
|
||||||
handleDownloadClick(activity, downloadClickEvent)
|
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) {
|
if (storedData?.url != null) {
|
||||||
result_reload_connectionerror.setOnClickListener {
|
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 {
|
result_reload_connection_open_in_browser?.setOnClickListener {
|
||||||
|
@ -952,7 +977,14 @@ open class ResultFragment : ResultTrailerPlayer() {
|
||||||
|
|
||||||
if (restart || !viewModel.hasLoaded()) {
|
if (restart || !viewModel.hasLoaded()) {
|
||||||
//viewModel.clear()
|
//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.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getId
|
import com.lagradost.cloudstream3.APIHolder.getId
|
||||||
import com.lagradost.cloudstream3.APIHolder.unixTime
|
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.getCastSession
|
||||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
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.syncproviders.providers.Kitsu
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
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.GeneratorPlayer
|
||||||
import com.lagradost.cloudstream3.ui.player.IGenerator
|
import com.lagradost.cloudstream3.ui.player.IGenerator
|
||||||
import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator
|
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.setResultEpisode
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
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.navigate
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
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 kotlinx.coroutines.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.Math.abs
|
import java.lang.Math.abs
|
||||||
|
@ -529,24 +536,16 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun downloadSubtitle(
|
private fun downloadSubtitle(
|
||||||
context: Context?,
|
|
||||||
link: ExtractorSubtitleLink,
|
link: ExtractorSubtitleLink,
|
||||||
fileName: String,
|
fileName: String,
|
||||||
folder: String
|
folder: String
|
||||||
) {
|
) {
|
||||||
ioSafe {
|
Aria2Starter.download(
|
||||||
VideoDownloadManager.downloadThing(
|
newUriRequest(
|
||||||
context ?: return@ioSafe,
|
null, link.url, fileName, folder, link.headers,
|
||||||
link,
|
USER_AGENT
|
||||||
"$fileName ${link.name}",
|
)
|
||||||
folder,
|
)
|
||||||
if (link.url.contains(".srt")) ".srt" else "vtt",
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
) {
|
|
||||||
// no notification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFolder(currentType: TvType, titleName: String): String {
|
private fun getFolder(currentType: TvType, titleName: String): String {
|
||||||
|
@ -576,7 +575,6 @@ class ResultViewModel2 : ViewModel() {
|
||||||
val fileName = VideoDownloadManager.getFileName(ctx, meta)
|
val fileName = VideoDownloadManager.getFileName(ctx, meta)
|
||||||
val folder = getFolder(meta.type ?: return, meta.mainName)
|
val folder = getFolder(meta.type ?: return, meta.mainName)
|
||||||
downloadSubtitle(
|
downloadSubtitle(
|
||||||
ctx,
|
|
||||||
ExtractorSubtitleLink(link.name, link.url, ""),
|
ExtractorSubtitleLink(link.name, link.url, ""),
|
||||||
fileName,
|
fileName,
|
||||||
folder
|
folder
|
||||||
|
@ -584,8 +582,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startDownload(
|
fun getDownloadRequest(
|
||||||
context: Context?,
|
|
||||||
episode: ResultEpisode,
|
episode: ResultEpisode,
|
||||||
currentIsMovie: Boolean,
|
currentIsMovie: Boolean,
|
||||||
currentHeaderName: String,
|
currentHeaderName: String,
|
||||||
|
@ -596,93 +593,182 @@ class ResultViewModel2 : ViewModel() {
|
||||||
url: String,
|
url: String,
|
||||||
links: List<ExtractorLink>,
|
links: List<ExtractorLink>,
|
||||||
subs: List<SubtitleData>?
|
subs: List<SubtitleData>?
|
||||||
) {
|
): DownloadRequest? {
|
||||||
try {
|
val meta =
|
||||||
if (context == null) return
|
getMeta(
|
||||||
|
episode,
|
||||||
val meta =
|
currentHeaderName,
|
||||||
getMeta(
|
apiName,
|
||||||
episode,
|
currentPoster,
|
||||||
currentHeaderName,
|
currentIsMovie,
|
||||||
apiName,
|
currentType
|
||||||
currentPoster,
|
|
||||||
currentIsMovie,
|
|
||||||
currentType
|
|
||||||
)
|
|
||||||
|
|
||||||
val folder = getFolder(currentType, currentHeaderName)
|
|
||||||
|
|
||||||
val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
|
|
||||||
|
|
||||||
// SET VISUAL KEYS
|
|
||||||
AcraApplication.setKey(
|
|
||||||
DOWNLOAD_HEADER_CACHE,
|
|
||||||
parentId.toString(),
|
|
||||||
VideoDownloadHelper.DownloadHeaderCached(
|
|
||||||
apiName,
|
|
||||||
url,
|
|
||||||
currentType,
|
|
||||||
currentHeaderName,
|
|
||||||
currentPoster,
|
|
||||||
parentId,
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
AcraApplication.setKey(
|
val topFolder = VideoDownloadManager.getDownloadDir()?.filePath
|
||||||
DataStore.getFolderName(
|
?: throw RuntimeException("FUCK YOU")//AcraApplication.context?.getBasePath()?.first //?.second?.also { println("URIIIIII: $it") } ?: throw RuntimeException("FUCK YOU")
|
||||||
DOWNLOAD_EPISODE_CACHE,
|
//?: VideoDownloadManager.getDownloadDir()?.filePath ?: return null
|
||||||
parentId.toString()
|
|
||||||
), // 3 deep folder for faster acess
|
|
||||||
episode.id.toString(),
|
|
||||||
VideoDownloadHelper.DownloadEpisodeCached(
|
|
||||||
episode.name,
|
|
||||||
episode.poster,
|
|
||||||
episode.episode,
|
|
||||||
episode.season,
|
|
||||||
episode.id,
|
|
||||||
parentId,
|
|
||||||
episode.rating,
|
|
||||||
episode.description,
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// DOWNLOAD VIDEO
|
val folder =
|
||||||
VideoDownloadManager.downloadEpisodeUsingWorker(
|
topFolder//topFolder?.gotoDir(getFolder(currentType, currentHeaderName).replace(".", ""), true)?.uri?.toString() ?: throw RuntimeException("FUCK YOU")
|
||||||
context,
|
//val folder =
|
||||||
src,//url ?: return,
|
// topFolder + "/" + getFolder(currentType, currentHeaderName).replace(".", "")
|
||||||
folder,
|
//val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let
|
||||||
meta,
|
|
||||||
links
|
|
||||||
)
|
|
||||||
|
|
||||||
// 1. Checks if the lang should be downloaded
|
// SET VISUAL KEYS
|
||||||
// 2. Makes it into the download format
|
AcraApplication.setKey(
|
||||||
// 3. Downloads it as a .vtt file
|
DOWNLOAD_HEADER_CACHE,
|
||||||
val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1()
|
parentId.toString(),
|
||||||
subs?.let { subsList ->
|
VideoDownloadHelper.DownloadHeaderCached(
|
||||||
subsList.filter {
|
apiName,
|
||||||
downloadList.contains(
|
url,
|
||||||
SubtitleHelper.fromLanguageToTwoLetters(
|
currentType,
|
||||||
it.name,
|
currentHeaderName,
|
||||||
true
|
currentPoster,
|
||||||
)
|
parentId,
|
||||||
)
|
System.currentTimeMillis(),
|
||||||
}
|
)
|
||||||
.map { ExtractorSubtitleLink(it.name, it.url, "") }
|
)
|
||||||
.forEach { link ->
|
|
||||||
val fileName = VideoDownloadManager.getFileName(context, meta)
|
AcraApplication.setKey(
|
||||||
downloadSubtitle(context, link, fileName, folder)
|
DataStore.getFolderName(
|
||||||
}
|
DOWNLOAD_EPISODE_CACHE,
|
||||||
|
parentId.toString()
|
||||||
|
), // 3 deep folder for faster acess
|
||||||
|
episode.id.toString(),
|
||||||
|
VideoDownloadHelper.DownloadEpisodeCached(
|
||||||
|
episode.name,
|
||||||
|
episode.poster,
|
||||||
|
episode.episode,
|
||||||
|
episode.season,
|
||||||
|
episode.id,
|
||||||
|
parentId,
|
||||||
|
episode.rating,
|
||||||
|
episode.description,
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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 ?: "") + ""
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
NotificationMetaData(
|
||||||
logError(e)
|
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
|
||||||
|
)
|
||||||
|
}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1()
|
||||||
|
val downloadSubsList = (subs ?: emptyList()).filter {
|
||||||
|
downloadList.contains(
|
||||||
|
SubtitleHelper.fromLanguageToTwoLetters(
|
||||||
|
it.name,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.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(
|
suspend fun downloadEpisode(
|
||||||
activity: Activity?,
|
|
||||||
episode: ResultEpisode,
|
episode: ResultEpisode,
|
||||||
currentIsMovie: Boolean,
|
currentIsMovie: Boolean,
|
||||||
currentHeaderName: String,
|
currentHeaderName: String,
|
||||||
|
@ -691,52 +777,49 @@ class ResultViewModel2 : ViewModel() {
|
||||||
apiName: String,
|
apiName: String,
|
||||||
parentId: Int,
|
parentId: Int,
|
||||||
url: String,
|
url: String,
|
||||||
) {
|
): DownloadRequest? {
|
||||||
ioSafe {
|
val generator = RepoLinkGenerator(listOf(episode))
|
||||||
val generator = RepoLinkGenerator(listOf(episode))
|
val currentLinks = mutableSetOf<ExtractorLink>()
|
||||||
val currentLinks = mutableSetOf<ExtractorLink>()
|
val currentSubs = mutableSetOf<SubtitleData>()
|
||||||
val currentSubs = mutableSetOf<SubtitleData>()
|
generator.generateLinks(clearCache = false, isCasting = false, callback = {
|
||||||
generator.generateLinks(clearCache = false, isCasting = false, callback = {
|
it.first?.let { link ->
|
||||||
it.first?.let { link ->
|
currentLinks.add(link)
|
||||||
currentLinks.add(link)
|
|
||||||
}
|
|
||||||
}, subtitleCallback = { sub ->
|
|
||||||
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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, subtitleCallback = { sub ->
|
||||||
|
currentSubs.add(sub)
|
||||||
|
})
|
||||||
|
|
||||||
startDownload(
|
//if (currentLinks.isEmpty()) {
|
||||||
activity,
|
// main {
|
||||||
episode,
|
// showToast(
|
||||||
currentIsMovie,
|
// activity,
|
||||||
currentHeaderName,
|
// R.string.no_links_found_toast,
|
||||||
currentType,
|
// Toast.LENGTH_SHORT
|
||||||
currentPoster,
|
// )
|
||||||
apiName,
|
// }
|
||||||
parentId,
|
// return@ioSafe
|
||||||
url,
|
//} else {
|
||||||
sortUrls(currentLinks),
|
// main {
|
||||||
sortSubs(currentSubs),
|
// showToast(
|
||||||
)
|
// activity,
|
||||||
}
|
// R.string.download_started,
|
||||||
|
// Toast.LENGTH_SHORT
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
return getDownloadRequest(
|
||||||
|
episode,
|
||||||
|
currentIsMovie,
|
||||||
|
currentHeaderName,
|
||||||
|
currentType,
|
||||||
|
currentPoster,
|
||||||
|
apiName,
|
||||||
|
parentId,
|
||||||
|
url,
|
||||||
|
sortUrls(currentLinks),
|
||||||
|
sortSubs(currentSubs),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMeta(
|
private fun getMeta(
|
||||||
|
@ -1021,6 +1104,42 @@ class ResultViewModel2 : ViewModel() {
|
||||||
handleEpisodeClickEvent(activity, click)
|
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) {
|
private suspend fun handleEpisodeClickEvent(activity: Activity?, click: EpisodeClickEvent) {
|
||||||
when (click.action) {
|
when (click.action) {
|
||||||
ACTION_SHOW_OPTIONS -> {
|
ACTION_SHOW_OPTIONS -> {
|
||||||
|
@ -1117,18 +1236,11 @@ class ResultViewModel2 : ViewModel() {
|
||||||
showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT)
|
showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT)
|
||||||
}
|
}
|
||||||
ACTION_DOWNLOAD_EPISODE -> {
|
ACTION_DOWNLOAD_EPISODE -> {
|
||||||
val response = currentResponse ?: return
|
ioSafe {
|
||||||
downloadEpisode(
|
val response = currentResponse ?: return@ioSafe
|
||||||
activity,
|
val req = getRequest(click.data) ?: return@ioSafe
|
||||||
click.data,
|
Aria2Starter.client?.downloadFailQueue(req.links) { _, _ -> }
|
||||||
response.isMovie(),
|
}
|
||||||
response.name,
|
|
||||||
response.type,
|
|
||||||
response.posterUrl,
|
|
||||||
response.apiName,
|
|
||||||
response.getId(),
|
|
||||||
response.url
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ACTION_DOWNLOAD_MIRROR -> {
|
ACTION_DOWNLOAD_MIRROR -> {
|
||||||
val response = currentResponse ?: return
|
val response = currentResponse ?: return
|
||||||
|
@ -1138,8 +1250,7 @@ class ResultViewModel2 : ViewModel() {
|
||||||
txt(R.string.episode_action_download_mirror)
|
txt(R.string.episode_action_download_mirror)
|
||||||
) { (result, index) ->
|
) { (result, index) ->
|
||||||
ioSafe {
|
ioSafe {
|
||||||
startDownload(
|
val req = getDownloadRequest(
|
||||||
activity,
|
|
||||||
click.data,
|
click.data,
|
||||||
response.isMovie(),
|
response.isMovie(),
|
||||||
response.name,
|
response.name,
|
||||||
|
@ -1150,13 +1261,9 @@ class ResultViewModel2 : ViewModel() {
|
||||||
response.url,
|
response.url,
|
||||||
listOf(result.links[index]),
|
listOf(result.links[index]),
|
||||||
result.subs,
|
result.subs,
|
||||||
)
|
) ?: return@ioSafe
|
||||||
|
downloadFromRequest(activity, req)
|
||||||
}
|
}
|
||||||
showToast(
|
|
||||||
activity,
|
|
||||||
R.string.download_started,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ACTION_RELOAD_EPISODE -> {
|
ACTION_RELOAD_EPISODE -> {
|
||||||
|
@ -1592,7 +1699,8 @@ class ResultViewModel2 : ViewModel() {
|
||||||
val idIndex = ep.key.id
|
val idIndex = ep.key.id
|
||||||
for ((index, i) in ep.value.withIndex()) {
|
for ((index, i) in ep.value.withIndex()) {
|
||||||
val episode = i.episode ?: (index + 1)
|
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)) {
|
if (!existingEpisodes.contains(id)) {
|
||||||
existingEpisodes.add(id)
|
existingEpisodes.add(id)
|
||||||
val seasonData = loadResponse.seasonNames.getSeason(i.season)
|
val seasonData = loadResponse.seasonNames.getSeason(i.season)
|
||||||
|
|
|
@ -22,15 +22,14 @@ import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
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.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.services.VideoDownloadService
|
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.ioSafe
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
|
@ -426,7 +425,7 @@ object VideoDownloadManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val reservedChars = "|\\?*<\":>+[]/\'"
|
private const val reservedChars = "|\\?*<\":>+[]/\'"
|
||||||
fun sanitizeFilename(name: String, removeSpaces: Boolean= false): String {
|
fun sanitizeFilename(name: String, removeSpaces: Boolean = false): String {
|
||||||
var tempName = name
|
var tempName = name
|
||||||
for (c in reservedChars) {
|
for (c in reservedChars) {
|
||||||
tempName = tempName.replace(c, ' ')
|
tempName = tempName.replace(c, ' ')
|
||||||
|
@ -531,6 +530,7 @@ object VideoDownloadManager {
|
||||||
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
|
MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY),
|
||||||
projection, selection, null, null
|
projection, selection, null, null
|
||||||
)
|
)
|
||||||
|
println("result:$result ${result?.count}")
|
||||||
|
|
||||||
result.use { c ->
|
result.use { c ->
|
||||||
if (c != null && c.count >= 1) {
|
if (c != null && c.count >= 1) {
|
||||||
|
@ -941,7 +941,7 @@ object VideoDownloadManager {
|
||||||
* @param directoryName if null will use the current path.
|
* @param directoryName if null will use the current path.
|
||||||
* @return UniFile / null if createMissingDirectories = false and folder is not found.
|
* @return UniFile / null if createMissingDirectories = false and folder is not found.
|
||||||
* */
|
* */
|
||||||
private fun UniFile.gotoDir(
|
fun UniFile.gotoDir(
|
||||||
directoryName: String?,
|
directoryName: String?,
|
||||||
createMissingDirectories: Boolean = true
|
createMissingDirectories: Boolean = true
|
||||||
): UniFile? {
|
): 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"
|
return "$name.$extension"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1487,27 +1487,50 @@ object VideoDownloadManager {
|
||||||
|
|
||||||
fun getDownloadFileInfoAndUpdateSettings(context: Context, id: Int): DownloadedFileInfoResult? {
|
fun getDownloadFileInfoAndUpdateSettings(context: Context, id: Int): DownloadedFileInfoResult? {
|
||||||
val res = getDownloadFileInfo(context, id)
|
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
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? {
|
private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? {
|
||||||
try {
|
try {
|
||||||
|
println("getDownloadFileInfo:$id")
|
||||||
|
|
||||||
val info =
|
val info =
|
||||||
context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return null
|
context.getKey<DownloadedFileInfo>(KEY_DOWNLOAD_INFO, id.toString()) ?: return null
|
||||||
val base = basePathToFile(context, info.basePath)
|
val base = basePathToFile(context, info.basePath)
|
||||||
|
println("BASE:$info")
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) {
|
||||||
val cr = context.contentResolver ?: return null
|
val cr = context.contentResolver ?: return null
|
||||||
|
println("CR:$cr")
|
||||||
|
|
||||||
val fileUri =
|
val fileUri =
|
||||||
cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName)
|
cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName)
|
||||||
?: return null
|
?: return null
|
||||||
|
println("FILEURI:$fileUri")
|
||||||
|
|
||||||
val fileLength = cr.getFileLength(fileUri) ?: return null
|
val fileLength = cr.getFileLength(fileUri) ?: return null
|
||||||
|
println("fileLength:$fileLength")
|
||||||
|
|
||||||
if (fileLength == 0L) return null
|
if (fileLength == 0L) return null
|
||||||
return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri)
|
return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri)
|
||||||
} else {
|
} else {
|
||||||
|
println("STUFF:$base")
|
||||||
|
|
||||||
val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName)
|
val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName)
|
||||||
|
println("file:$file")
|
||||||
|
|
||||||
// val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName)
|
// val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName)
|
||||||
// val dFile = File(normalPath)
|
// val dFile = File(normalPath)
|
||||||
|
@ -1612,20 +1635,20 @@ object VideoDownloadManager {
|
||||||
.mapIndexed { index, any -> DownloadQueueResumePackage(index, any) }
|
.mapIndexed { index, any -> DownloadQueueResumePackage(index, any) }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
setKey(KEY_RESUME_QUEUE_PACKAGES, dQueue)
|
setKey(KEY_RESUME_QUEUE_PACKAGES, dQueue)
|
||||||
} catch (t : Throwable) {
|
} catch (t: Throwable) {
|
||||||
logError(t)
|
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?
|
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
|
||||||
for (service in manager!!.getRunningServices(Int.MAX_VALUE)) {
|
for (service in manager!!.getRunningServices(Int.MAX_VALUE)) {
|
||||||
if (serviceClass.name == service.service.className) {
|
if (serviceClass.name == service.service.className) {
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
}
|
||||||
}*/
|
return false
|
||||||
|
}*/
|
||||||
|
|
||||||
fun downloadEpisode(
|
fun downloadEpisode(
|
||||||
context: Context?,
|
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>
|
|
@ -1,118 +1,95 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:nextFocusRight="@id/download_child_episode_download"
|
android:id="@+id/download_child_episode_holder"
|
||||||
android:nextFocusLeft="@id/nav_rail_view"
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
android:id="@+id/download_child_episode_holder"
|
android:layout_height="50dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginBottom="5dp"
|
||||||
android:layout_height="50dp"
|
android:foreground="@drawable/outline_drawable"
|
||||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
android:nextFocusLeft="@id/nav_rail_view"
|
||||||
app:cardBackgroundColor="@color/transparent"
|
android:nextFocusRight="@id/download_child_episode_download"
|
||||||
app:cardElevation="0dp"
|
app:cardBackgroundColor="@color/transparent"
|
||||||
android:foreground="@drawable/outline_drawable"
|
app:cardCornerRadius="@dimen/rounded_image_radius"
|
||||||
android:layout_marginBottom="5dp">
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:id="@+id/download_child_episode_progress"
|
android:id="@+id/download_child_episode_progress"
|
||||||
|
|
||||||
android:layout_marginBottom="-1.5dp"
|
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||||
android:progressTint="?attr/colorPrimary"
|
android:layout_width="match_parent"
|
||||||
android:progressBackgroundTint="?attr/colorPrimary"
|
android:layout_height="5dp"
|
||||||
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
android:layout_gravity="bottom"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginBottom="-1.5dp"
|
||||||
tools:progress="50"
|
android:progressBackgroundTint="?attr/colorPrimary"
|
||||||
android:layout_gravity="bottom"
|
android:progressTint="?attr/colorPrimary"
|
||||||
android:layout_height="5dp" />
|
tools:progress="50" />
|
||||||
|
|
||||||
<GridLayout
|
<GridLayout
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:foreground="?android:attr/selectableItemBackgroundBorderless">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/download_child_episode_play"
|
android:id="@+id/download_child_episode_play"
|
||||||
android:visibility="gone"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_marginEnd="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:src="@drawable/ic_baseline_play_arrow_24"
|
||||||
android:contentDescription="@string/episode_play_img_des" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="50dp"
|
||||||
|
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_gravity="center_vertical"
|
||||||
android:orientation="vertical"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginEnd="50dp"
|
|
||||||
android:layout_width="match_parent">
|
android:ellipsize="marquee"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:marqueeRepeatLimit="marquee_forever"
|
||||||
|
android:scrollHorizontally="true"
|
||||||
|
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_child_episode_text"
|
android:id="@+id/download_child_episode_text_extra"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:gravity="center_vertical"
|
android:layout_marginStart="10dp"
|
||||||
tools:text="Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1 Episode 1"
|
android:layout_marginEnd="10dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:scrollHorizontally="true"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:ellipsize="marquee"
|
tools:text="128MB / 237MB" />
|
||||||
android:marqueeRepeatLimit="marquee_forever"
|
|
||||||
android:singleLine="true"
|
|
||||||
|
|
||||||
android:textColor="?attr/textColor"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/download_child_episode_text_extra"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
tools:text="128MB / 237MB"
|
|
||||||
android:textColor="?attr/grayTextColor"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
</LinearLayout>
|
</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>
|
</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>
|
</androidx.cardview.widget.CardView>
|
|
@ -1,103 +1,66 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/episode_holder"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
android:layout_height="wrap_content"
|
||||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
android:layout_marginStart="10dp"
|
||||||
android:id="@+id/episode_holder"
|
android:layout_marginTop="10dp"
|
||||||
android:foreground="@drawable/outline_drawable"
|
android:layout_marginEnd="10dp"
|
||||||
android:layout_marginStart="10dp"
|
android:foreground="@drawable/outline_drawable"
|
||||||
android:layout_marginEnd="10dp"
|
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||||
android:layout_marginTop="10dp">
|
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="horizontal">
|
||||||
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="70dp"
|
android:layout_width="70dp"
|
||||||
android:layout_height="104dp">
|
android:layout_height="104dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/download_header_poster"
|
android:id="@+id/download_header_poster"
|
||||||
tools:src="@drawable/example_poster"
|
android:layout_width="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:contentDescription="@string/episode_poster_img_des"
|
||||||
android:layout_height="match_parent"
|
android:scaleType="centerCrop"
|
||||||
android:contentDescription="@string/episode_poster_img_des" />
|
tools:src="@drawable/example_poster" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="15dp"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="70dp"
|
android:layout_marginEnd="50dp"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/download_header_title"
|
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" />
|
|
||||||
|
|
||||||
<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_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?attr/textColor"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="Perfect Run" />
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<TextView
|
||||||
android:layout_marginEnd="10dp"
|
android:id="@+id/download_header_info"
|
||||||
android:layout_marginStart="10dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="40dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="40dp"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:id="@+id/download_header_progress_downloaded"
|
tools:text="1 episode | 285MB" />
|
||||||
android:indeterminate="false"
|
</LinearLayout>
|
||||||
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>
|
|
||||||
</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>
|
</androidx.cardview.widget.CardView>
|
|
@ -569,90 +569,12 @@
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:layout_width="match_parent" />-->
|
android:layout_width="match_parent" />-->
|
||||||
|
<com.lagradost.cloudstream3.ui.DownloadButton
|
||||||
<FrameLayout
|
android:id="@+id/result_download_movie"
|
||||||
android:id="@+id/result_movie_progress_downloaded_holder"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_gravity="center"
|
||||||
|
app:aria2c_layout="@layout/download_button_layout" />
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
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>
|
|
||||||
|
|
||||||
|
|
||||||
<!--<androidx.core.widget.ContentLoadingProgressBar
|
<!--<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -418,109 +418,25 @@
|
||||||
|
|
||||||
</com.google.android.material.button.MaterialButton>
|
</com.google.android.material.button.MaterialButton>
|
||||||
|
|
||||||
|
<com.lagradost.cloudstream3.ui.DownloadButton
|
||||||
<FrameLayout
|
android:id="@+id/result_download_movie"
|
||||||
android:nextFocusRight="@id/result_bookmark_button"
|
|
||||||
android:id="@+id/result_movie_progress_downloaded_holder"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:minWidth="250dp">
|
android:minWidth="250dp"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
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>
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<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"
|
android:id="@+id/result_bookmark_button"
|
||||||
style="@style/BlackButton"
|
style="@style/BlackButton"
|
||||||
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:minWidth="250dp"
|
android:minWidth="250dp"
|
||||||
|
android:nextFocusLeft="@id/result_download_movie"
|
||||||
|
android:nextFocusDown="@id/result_resume_series_button_play"
|
||||||
android:text="@string/type_none"
|
android:text="@string/type_none"
|
||||||
android:visibility="visible" />
|
android:visibility="visible" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -95,35 +95,13 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
android:layout_marginEnd="10dp"
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:layout_marginStart="10dp"
|
android:id="@+id/result_episode_download"
|
||||||
android:layout_width="40dp"
|
android:layout_gravity="center"
|
||||||
android:layout_height="40dp"
|
android:padding="10dp"
|
||||||
android:id="@+id/result_episode_progress_downloaded"
|
android:layout_width="50dp"
|
||||||
android:indeterminate="false"
|
android:layout_height="50dp">
|
||||||
android:progressDrawable="@drawable/circular_progress_bar"
|
</com.lagradost.fetchbutton.ui.PieFetchButton>
|
||||||
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"
|
|
||||||
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"
|
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
|
||||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
|
||||||
android:contentDescription="@string/download" />
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -1,151 +1,130 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:nextFocusRight="@id/result_episode_download"
|
android:id="@+id/episode_holder_large"
|
||||||
android:id="@+id/episode_holder_large"
|
android:layout_width="match_parent"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginBottom="10dp"
|
||||||
app:cardCornerRadius="@dimen/rounded_image_radius"
|
android:nextFocusRight="@id/result_episode_download"
|
||||||
app:cardBackgroundColor="?attr/boxItemBackground"
|
app:cardBackgroundColor="?attr/boxItemBackground"
|
||||||
|
|
||||||
android:layout_marginBottom="10dp">
|
app:cardCornerRadius="@dimen/rounded_image_radius">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:layout_width="match_parent"
|
||||||
android:padding="10dp"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_width="match_parent"
|
android:orientation="vertical"
|
||||||
android:layout_height="wrap_content">
|
android:padding="10dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
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"-->
|
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="126dp"
|
android:layout_width="126dp"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:foreground="@drawable/outline_drawable">
|
android:foreground="@drawable/outline_drawable">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:nextFocusRight="@id/result_episode_download"
|
android:id="@+id/episode_poster"
|
||||||
|
|
||||||
android:id="@+id/episode_poster"
|
android:layout_width="match_parent"
|
||||||
tools:src="@drawable/example_poster"
|
android:layout_height="match_parent"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:contentDescription="@string/episode_poster_img_des"
|
||||||
|
|
||||||
android:scaleType="centerCrop"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_width="match_parent"
|
android:nextFocusRight="@id/result_episode_download"
|
||||||
android:layout_height="match_parent"
|
android:scaleType="centerCrop"
|
||||||
android:contentDescription="@string/episode_poster_img_des" />
|
tools:src="@drawable/example_poster" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:src="@drawable/play_button"
|
android:layout_width="36dp"
|
||||||
android:layout_gravity="center"
|
android:layout_height="36dp"
|
||||||
android:layout_width="36dp"
|
android:layout_gravity="center"
|
||||||
android:layout_height="36dp"
|
android:contentDescription="@string/play_episode"
|
||||||
android:contentDescription="@string/play_episode" />
|
android:src="@drawable/play_button" />
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:layout_marginBottom="-1.5dp"
|
android:id="@+id/episode_progress"
|
||||||
android:id="@+id/episode_progress"
|
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
||||||
android:progressTint="?attr/colorPrimary"
|
android:layout_width="match_parent"
|
||||||
android:progressBackgroundTint="?attr/colorPrimary"
|
android:layout_height="5dp"
|
||||||
style="@android:style/Widget.Material.ProgressBar.Horizontal"
|
android:layout_gravity="bottom"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginBottom="-1.5dp"
|
||||||
tools:progress="50"
|
android:progressBackgroundTint="?attr/colorPrimary"
|
||||||
android:layout_gravity="bottom"
|
android:progressTint="?attr/colorPrimary"
|
||||||
android:layout_height="5dp" />
|
tools:progress="50" />
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="15dp"
|
android:layout_width="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_marginEnd="50dp"
|
android:layout_marginEnd="50dp"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:layout_gravity="start"
|
android:id="@+id/episode_filler"
|
||||||
style="@style/SmallBlackButton"
|
style="@style/SmallBlackButton"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_gravity="start"
|
||||||
android:text="@string/filler"
|
android:layout_marginEnd="10dp"
|
||||||
android:id="@+id/episode_filler" />
|
android:text="@string/filler" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_gravity="center_vertical"
|
android:id="@+id/episode_text"
|
||||||
android:id="@+id/episode_text"
|
android:layout_width="wrap_content"
|
||||||
tools:text="1. Jobless"
|
android:layout_height="wrap_content"
|
||||||
android:textStyle="bold"
|
android:layout_gravity="center_vertical"
|
||||||
android:textColor="?attr/textColor"
|
android:textColor="?attr/textColor"
|
||||||
android:layout_width="wrap_content"
|
android:textStyle="bold"
|
||||||
android:layout_height="wrap_content" />
|
tools:text="1. Jobless" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/episode_rating"
|
android:id="@+id/episode_rating"
|
||||||
tools:text="Rated: 8.8"
|
android:layout_width="wrap_content"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:textColor="?attr/grayTextColor"
|
||||||
android:layout_height="wrap_content" />
|
tools:text="Rated: 8.8" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_marginStart="-50dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_gravity="end"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_gravity="end"
|
||||||
android:layout_height="match_parent">
|
android:layout_marginStart="-50dp">
|
||||||
|
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<com.lagradost.fetchbutton.ui.PieFetchButton
|
||||||
android:layout_marginEnd="10dp"
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:layout_marginStart="10dp"
|
android:id="@+id/result_episode_download"
|
||||||
android:layout_width="40dp"
|
android:layout_gravity="center"
|
||||||
android:layout_height="40dp"
|
android:padding="5dp"
|
||||||
android:id="@+id/result_episode_progress_downloaded"
|
android:layout_width="50dp"
|
||||||
android:indeterminate="false"
|
android:layout_height="50dp">
|
||||||
android:progressDrawable="@drawable/circular_progress_bar"
|
</com.lagradost.fetchbutton.ui.PieFetchButton>
|
||||||
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"
|
|
||||||
android:background="?selectableItemBackgroundBorderless"
|
|
||||||
android:src="@drawable/ic_baseline_play_arrow_24"
|
|
||||||
android:contentDescription="@string/download"
|
|
||||||
app:tint="?attr/white" />
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:maxLines="4"
|
android:id="@+id/episode_descript"
|
||||||
android:ellipsize="end"
|
android:layout_width="match_parent"
|
||||||
android:paddingTop="10dp"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="10dp"
|
android:ellipsize="end"
|
||||||
android:id="@+id/episode_descript"
|
android:maxLines="4"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:paddingTop="10dp"
|
||||||
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:paddingBottom="10dp"
|
||||||
android:layout_width="match_parent"
|
android:textColor="?attr/grayTextColor"
|
||||||
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>
|
</LinearLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
|
@ -22,6 +22,10 @@
|
||||||
<color name="white">#FFF</color>
|
<color name="white">#FFF</color>
|
||||||
<color name="black">#000</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="dubColor">#3d50fa</color> <!--3b65f5 f18c82 8294F1-->
|
||||||
<color name="amoledModeLight">#121213</color>
|
<color name="amoledModeLight">#121213</color>
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,14 @@
|
||||||
|
|
||||||
<item name="android:windowAllowReturnTransitionOverlap">true</item>
|
<item name="android:windowAllowReturnTransitionOverlap">true</item>
|
||||||
<item name="android:windowAllowEnterTransitionOverlap">true</item>
|
<item name="android:windowAllowEnterTransitionOverlap">true</item>
|
||||||
|
|
||||||
<!--<item name="preferenceTheme">@style/PreferencesTheme</item>-->
|
<!--<item name="preferenceTheme">@style/PreferencesTheme</item>-->
|
||||||
|
|
||||||
<!-- DEF STYLE -->
|
<!-- DEF STYLE -->
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
|
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="textColor">@color/textColor</item>
|
<item name="textColor">@color/textColor</item>
|
||||||
<item name="grayTextColor">@color/grayTextColor</item>
|
<item name="grayTextColor">@color/grayTextColor</item>
|
||||||
|
@ -65,6 +68,10 @@
|
||||||
<item name="white">#FFF</item>
|
<item name="white">#FFF</item>
|
||||||
|
|
||||||
<item name="preferenceTheme">@style/CustomPreferenceThemeOverlay</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>
|
||||||
|
|
||||||
<style name="ListViewStyle" parent="Widget.AppCompat.ListView">
|
<style name="ListViewStyle" parent="Widget.AppCompat.ListView">
|
||||||
|
@ -100,7 +107,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimary</item>
|
<item name="android:colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
<item name="colorOnPrimary">@color/colorAccent</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorAccent</item>
|
<item name="android:colorAccent">@color/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -110,7 +117,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryBlue</item>
|
<item name="android:colorPrimary">@color/colorPrimaryBlue</item>
|
||||||
<item name="colorPrimaryDark">#4855A2</item>
|
<item name="colorPrimaryDark">#4855A2</item>
|
||||||
<item name="colorAccent">#5A6BCB</item>
|
<item name="colorAccent">#5A6BCB</item>
|
||||||
<item name="colorOnPrimary">#5A6BCB</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryBlue</item>
|
<item name="android:colorAccent">@color/colorPrimaryBlue</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -120,7 +127,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryPurple</item>
|
<item name="android:colorPrimary">@color/colorPrimaryPurple</item>
|
||||||
<item name="colorPrimaryDark">#4704A3</item>
|
<item name="colorPrimaryDark">#4704A3</item>
|
||||||
<item name="colorAccent">#7125DB</item>
|
<item name="colorAccent">#7125DB</item>
|
||||||
<item name="colorOnPrimary">#7125DB</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryPurple</item>
|
<item name="android:colorAccent">@color/colorPrimaryPurple</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -129,7 +136,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryGreen</item>
|
<item name="android:colorPrimary">@color/colorPrimaryGreen</item>
|
||||||
<item name="colorPrimaryDark">#007363</item>
|
<item name="colorPrimaryDark">#007363</item>
|
||||||
<item name="colorAccent">#39C1AE</item>
|
<item name="colorAccent">#39C1AE</item>
|
||||||
<item name="colorOnPrimary">#39C1AE</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryGreen</item>
|
<item name="android:colorAccent">@color/colorPrimaryGreen</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -138,7 +145,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryGreenApple</item>
|
<item name="android:colorPrimary">@color/colorPrimaryGreenApple</item>
|
||||||
<item name="colorPrimaryDark">#319B5A</item>
|
<item name="colorPrimaryDark">#319B5A</item>
|
||||||
<item name="colorAccent">#51C57E</item>
|
<item name="colorAccent">#51C57E</item>
|
||||||
<item name="colorOnPrimary">#51C57E</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryGreenApple</item>
|
<item name="android:colorAccent">@color/colorPrimaryGreenApple</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -147,7 +154,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryRed</item>
|
<item name="android:colorPrimary">@color/colorPrimaryRed</item>
|
||||||
<item name="colorPrimaryDark">#B62B2B</item>
|
<item name="colorPrimaryDark">#B62B2B</item>
|
||||||
<item name="colorAccent">@color/colorPrimaryRed</item> <!--#F53B3B-->
|
<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 -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryRed</item>
|
<item name="android:colorAccent">@color/colorPrimaryRed</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -157,7 +164,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryBanana</item>
|
<item name="android:colorPrimary">@color/colorPrimaryBanana</item>
|
||||||
<item name="colorPrimaryDark">#9B7D31</item>
|
<item name="colorPrimaryDark">#9B7D31</item>
|
||||||
<item name="colorAccent">#C5B251</item>
|
<item name="colorAccent">#C5B251</item>
|
||||||
<item name="colorOnPrimary">#C5A851</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryBanana</item>
|
<item name="android:colorAccent">@color/colorPrimaryBanana</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -166,7 +173,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryParty</item>
|
<item name="android:colorPrimary">@color/colorPrimaryParty</item>
|
||||||
<item name="colorPrimaryDark">#C1495B</item>
|
<item name="colorPrimaryDark">#C1495B</item>
|
||||||
<item name="colorAccent">#FD798C</item>
|
<item name="colorAccent">#FD798C</item>
|
||||||
<item name="colorOnPrimary">#BF5968</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryParty</item>
|
<item name="android:colorAccent">@color/colorPrimaryParty</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -175,7 +182,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryPink</item>
|
<item name="android:colorPrimary">@color/colorPrimaryPink</item>
|
||||||
<item name="colorPrimaryDark">#DD1280</item>
|
<item name="colorPrimaryDark">#DD1280</item>
|
||||||
<item name="colorAccent">#FF4DAE</item>
|
<item name="colorAccent">#FF4DAE</item>
|
||||||
<item name="colorOnPrimary">#DD1280</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<item name="android:colorAccent">@color/colorPrimaryPink</item>
|
<item name="android:colorAccent">@color/colorPrimaryPink</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
@ -184,7 +191,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryCarnationPink</item>
|
<item name="android:colorPrimary">@color/colorPrimaryCarnationPink</item>
|
||||||
<item name="colorPrimaryDark">#83366f</item>
|
<item name="colorPrimaryDark">#83366f</item>
|
||||||
<item name="colorAccent">#BD5DA5</item>
|
<item name="colorAccent">#BD5DA5</item>
|
||||||
<item name="colorOnPrimary">#BD5DA5</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryCarnationPink</item>
|
<item name="android:colorAccent">@color/colorPrimaryCarnationPink</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -194,7 +201,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryMaroon</item>
|
<item name="android:colorPrimary">@color/colorPrimaryMaroon</item>
|
||||||
<item name="colorPrimaryDark">#370C0C</item>
|
<item name="colorPrimaryDark">#370C0C</item>
|
||||||
<item name="colorAccent">#451010</item>
|
<item name="colorAccent">#451010</item>
|
||||||
<item name="colorOnPrimary">#451010</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryMaroon</item>
|
<item name="android:colorAccent">@color/colorPrimaryMaroon</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -204,7 +211,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryDarkGreen</item>
|
<item name="android:colorPrimary">@color/colorPrimaryDarkGreen</item>
|
||||||
<item name="colorPrimaryDark">#003d00</item>
|
<item name="colorPrimaryDark">#003d00</item>
|
||||||
<item name="colorAccent">#004500</item>
|
<item name="colorAccent">#004500</item>
|
||||||
<item name="colorOnPrimary">#004500</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryDarkGreen</item>
|
<item name="android:colorAccent">@color/colorPrimaryDarkGreen</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -214,7 +221,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryNavyBlue</item>
|
<item name="android:colorPrimary">@color/colorPrimaryNavyBlue</item>
|
||||||
<item name="colorPrimaryDark">#000073</item>
|
<item name="colorPrimaryDark">#000073</item>
|
||||||
<item name="colorAccent">#000080</item>
|
<item name="colorAccent">#000080</item>
|
||||||
<item name="colorOnPrimary">#000080</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryNavyBlue</item>
|
<item name="android:colorAccent">@color/colorPrimaryNavyBlue</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -224,7 +231,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryGrey</item>
|
<item name="android:colorPrimary">@color/colorPrimaryGrey</item>
|
||||||
<item name="colorPrimaryDark">#484848</item>
|
<item name="colorPrimaryDark">#484848</item>
|
||||||
<item name="colorAccent">#515151</item>
|
<item name="colorAccent">#515151</item>
|
||||||
<item name="colorOnPrimary">#515151</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryGrey</item>
|
<item name="android:colorAccent">@color/colorPrimaryGrey</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -234,7 +241,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryWhite</item>
|
<item name="android:colorPrimary">@color/colorPrimaryWhite</item>
|
||||||
<item name="colorPrimaryDark">#CCCCCC</item>
|
<item name="colorPrimaryDark">#CCCCCC</item>
|
||||||
<item name="colorAccent">#FFFFFF</item>
|
<item name="colorAccent">#FFFFFF</item>
|
||||||
<item name="colorOnPrimary">#FFFFFF</item>
|
<item name="colorOnPrimary">@color/blackText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryWhite</item>
|
<item name="android:colorAccent">@color/colorPrimaryWhite</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -244,7 +251,7 @@
|
||||||
<item name="android:colorPrimary">@color/colorPrimaryBrown</item>
|
<item name="android:colorPrimary">@color/colorPrimaryBrown</item>
|
||||||
<item name="colorPrimaryDark">#582700</item>
|
<item name="colorPrimaryDark">#582700</item>
|
||||||
<item name="colorAccent">#622C00</item>
|
<item name="colorAccent">#622C00</item>
|
||||||
<item name="colorOnPrimary">#622C00</item>
|
<item name="colorOnPrimary">@color/whiteText</item>
|
||||||
<!-- Needed for leanback fuckery -->
|
<!-- Needed for leanback fuckery -->
|
||||||
<item name="android:colorAccent">@color/colorPrimaryBrown</item>
|
<item name="android:colorAccent">@color/colorPrimaryBrown</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue