mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Add support for Next Episode in downloads (#1228)
This commit is contained in:
parent
4d9a080341
commit
f6a65f38db
7 changed files with 81 additions and 43 deletions
|
@ -1,9 +1,11 @@
|
||||||
package com.lagradost.cloudstream3.ui.download
|
package com.lagradost.cloudstream3.ui.download
|
||||||
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
|
import android.net.Uri
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||||
|
import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
|
||||||
import com.lagradost.cloudstream3.CommonActivity.activity
|
import com.lagradost.cloudstream3.CommonActivity.activity
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
@ -12,6 +14,7 @@ import com.lagradost.cloudstream3.ui.player.ExtractorUri
|
||||||
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
import com.lagradost.cloudstream3.ui.player.GeneratorPlayer
|
||||||
import com.lagradost.cloudstream3.utils.AppContextUtils.getNameFull
|
import com.lagradost.cloudstream3.utils.AppContextUtils.getNameFull
|
||||||
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
|
import com.lagradost.cloudstream3.utils.AppContextUtils.setDefaultFocus
|
||||||
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE
|
||||||
import com.lagradost.cloudstream3.utils.SnackbarHelper.showSnackbar
|
import com.lagradost.cloudstream3.utils.SnackbarHelper.showSnackbar
|
||||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||||
|
@ -109,57 +112,70 @@ object DownloadButtonSetup {
|
||||||
|
|
||||||
DOWNLOAD_ACTION_PLAY_FILE -> {
|
DOWNLOAD_ACTION_PLAY_FILE -> {
|
||||||
activity?.let { act ->
|
activity?.let { act ->
|
||||||
val info =
|
|
||||||
VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(
|
|
||||||
act,
|
|
||||||
click.data.id
|
|
||||||
) ?: return
|
|
||||||
val keyInfo = getKey<VideoDownloadManager.DownloadedFileInfo>(
|
|
||||||
VideoDownloadManager.KEY_DOWNLOAD_INFO,
|
|
||||||
click.data.id.toString()
|
|
||||||
) ?: return
|
|
||||||
val parent = getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
val parent = getKey<VideoDownloadHelper.DownloadHeaderCached>(
|
||||||
DOWNLOAD_HEADER_CACHE,
|
DOWNLOAD_HEADER_CACHE,
|
||||||
click.data.parentId.toString()
|
click.data.parentId.toString()
|
||||||
) ?: return
|
) ?: return
|
||||||
|
|
||||||
act.navigate(
|
val episodes = getKeys(DOWNLOAD_EPISODE_CACHE)
|
||||||
R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
|
?.mapNotNull {
|
||||||
DownloadFileGenerator(
|
getKey<VideoDownloadHelper.DownloadEpisodeCached>(it)
|
||||||
listOf(
|
}
|
||||||
ExtractorUri(
|
?.filter { it.parentId == click.data.parentId }
|
||||||
uri = info.path,
|
|
||||||
|
|
||||||
id = click.data.id,
|
val currentSeason = click.data.season ?: 0
|
||||||
parentId = click.data.parentId,
|
val currentEpisode = click.data.episode
|
||||||
name = act.getString(R.string.downloaded_file), // click.data.name ?: keyInfo.displayName
|
|
||||||
season = click.data.season,
|
val items = mutableListOf<ExtractorUri>()
|
||||||
episode = click.data.episode,
|
|
||||||
|
// Make sure we only get this episode and episodes after it,
|
||||||
|
// and that we can go to the next season if we need to.
|
||||||
|
val allRelevantEpisodes = episodes
|
||||||
|
?.sortedWith(
|
||||||
|
compareByDescending<VideoDownloadHelper.DownloadEpisodeCached> { it.id == click.data.id }
|
||||||
|
.thenBy { it.season ?: 0 }
|
||||||
|
.thenBy { it.episode }
|
||||||
|
)
|
||||||
|
?.filter {
|
||||||
|
if (it.season == null) return@filter true
|
||||||
|
val isCurrentOrLaterInSeason = it.season == currentSeason && (it.episode >= currentEpisode || it.id == click.data.id)
|
||||||
|
val isInFutureSeasons = it.season > currentSeason
|
||||||
|
|
||||||
|
isCurrentOrLaterInSeason || isInFutureSeasons
|
||||||
|
}
|
||||||
|
|
||||||
|
allRelevantEpisodes?.forEach {
|
||||||
|
val keyInfo = getKey<VideoDownloadManager.DownloadedFileInfo>(
|
||||||
|
VideoDownloadManager.KEY_DOWNLOAD_INFO,
|
||||||
|
it.id.toString()
|
||||||
|
) ?: return@forEach
|
||||||
|
|
||||||
|
items.add(
|
||||||
|
ExtractorUri(
|
||||||
|
// We just use a temporary placeholder for the URI,
|
||||||
|
// it will be updated in generateLinks().
|
||||||
|
// We just do this for performance since getting
|
||||||
|
// all paths at once can be quite expensive.
|
||||||
|
uri = Uri.EMPTY,
|
||||||
|
id = it.id,
|
||||||
|
parentId = it.parentId,
|
||||||
|
name = act.getString(R.string.downloaded_file),
|
||||||
|
season = it.season,
|
||||||
|
episode = it.episode,
|
||||||
headerName = parent.name,
|
headerName = parent.name,
|
||||||
tvType = parent.type,
|
tvType = parent.type,
|
||||||
|
|
||||||
basePath = keyInfo.basePath,
|
basePath = keyInfo.basePath,
|
||||||
displayName = keyInfo.displayName,
|
displayName = keyInfo.displayName,
|
||||||
relativePath = keyInfo.relativePath,
|
relativePath = keyInfo.relativePath,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
act.navigate(
|
||||||
|
R.id.global_to_navigation_player, GeneratorPlayer.newInstance(
|
||||||
|
DownloadFileGenerator(items)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
// R.id.global_to_navigation_player, PlayerFragment.newInstance(
|
|
||||||
// UriData(
|
|
||||||
// info.path.toString(),
|
|
||||||
// keyInfo.basePath,
|
|
||||||
// keyInfo.relativePath,
|
|
||||||
// keyInfo.displayName,
|
|
||||||
// click.data.parentId,
|
|
||||||
// click.data.id,
|
|
||||||
// headerName ?: "null",
|
|
||||||
// if (click.data.episode <= 0) null else click.data.episode,
|
|
||||||
// click.data.season
|
|
||||||
// ),
|
|
||||||
// getViewPos(click.data.id)?.position ?: 0
|
|
||||||
// )
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package com.lagradost.cloudstream3.ui.player
|
package com.lagradost.cloudstream3.ui.player
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
import com.lagradost.cloudstream3.AcraApplication.Companion.context
|
import com.lagradost.cloudstream3.AcraApplication.Companion.context
|
||||||
|
import com.lagradost.cloudstream3.CommonActivity.activity
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType
|
import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleUtils.cleanDisplayName
|
import com.lagradost.cloudstream3.utils.SubtitleUtils.cleanDisplayName
|
||||||
import com.lagradost.cloudstream3.utils.SubtitleUtils.isMatchingSubtitle
|
import com.lagradost.cloudstream3.utils.SubtitleUtils.isMatchingSubtitle
|
||||||
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getDownloadFileInfoAndUpdateSettings
|
||||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getFolder
|
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getFolder
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
@ -15,6 +18,7 @@ class DownloadFileGenerator(
|
||||||
private var currentIndex: Int = 0
|
private var currentIndex: Int = 0
|
||||||
) : IGenerator {
|
) : IGenerator {
|
||||||
override val hasCache = false
|
override val hasCache = false
|
||||||
|
override val canSkipLoading = false
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
return currentIndex < episodes.size - 1
|
return currentIndex < episodes.size - 1
|
||||||
|
@ -59,7 +63,21 @@ class DownloadFileGenerator(
|
||||||
offset: Int
|
offset: Int
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val meta = episodes[currentIndex + offset]
|
val meta = episodes[currentIndex + offset]
|
||||||
callback(null to meta)
|
|
||||||
|
if (meta.uri == Uri.EMPTY) {
|
||||||
|
// We do this here so that we only load it when
|
||||||
|
// we actually need it as it can be more expensive.
|
||||||
|
val info = meta.id?.let { id ->
|
||||||
|
activity?.let { act ->
|
||||||
|
getDownloadFileInfoAndUpdateSettings(act, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info != null) {
|
||||||
|
val newMeta = meta.copy(uri = info.path)
|
||||||
|
callback(null to newMeta)
|
||||||
|
} else callback(null to meta)
|
||||||
|
} else callback(null to meta)
|
||||||
|
|
||||||
val ctx = context ?: return true
|
val ctx = context ?: return true
|
||||||
val relative = meta.relativePath ?: return true
|
val relative = meta.relativePath ?: return true
|
||||||
|
|
|
@ -7,6 +7,7 @@ class ExtractorLinkGenerator(
|
||||||
private val subtitles: List<SubtitleData>,
|
private val subtitles: List<SubtitleData>,
|
||||||
) : IGenerator {
|
) : IGenerator {
|
||||||
override val hasCache = false
|
override val hasCache = false
|
||||||
|
override val canSkipLoading = true
|
||||||
|
|
||||||
override fun getCurrentId(): Int? {
|
override fun getCurrentId(): Int? {
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -1462,7 +1462,7 @@ class GeneratorPlayer : FullScreenPlayer() {
|
||||||
|
|
||||||
observe(viewModel.currentLinks) {
|
observe(viewModel.currentLinks) {
|
||||||
currentLinks = it
|
currentLinks = it
|
||||||
val turnVisible = it.isNotEmpty()
|
val turnVisible = it.isNotEmpty() && lastUsedGenerator?.canSkipLoading == true
|
||||||
val wasGone = binding?.overlayLoadingSkipButton?.isGone == true
|
val wasGone = binding?.overlayLoadingSkipButton?.isGone == true
|
||||||
binding?.overlayLoadingSkipButton?.isVisible = turnVisible
|
binding?.overlayLoadingSkipButton?.isVisible = turnVisible
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ fun LoadType.toSet() : Set<ExtractorLinkType> {
|
||||||
|
|
||||||
interface IGenerator {
|
interface IGenerator {
|
||||||
val hasCache: Boolean
|
val hasCache: Boolean
|
||||||
|
val canSkipLoading: Boolean
|
||||||
|
|
||||||
fun hasNext(): Boolean
|
fun hasNext(): Boolean
|
||||||
fun hasPrev(): Boolean
|
fun hasPrev(): Boolean
|
||||||
|
|
|
@ -39,6 +39,7 @@ class LinkGenerator(
|
||||||
private val isM3u8: Boolean? = null
|
private val isM3u8: Boolean? = null
|
||||||
) : IGenerator {
|
) : IGenerator {
|
||||||
override val hasCache = false
|
override val hasCache = false
|
||||||
|
override val canSkipLoading = true
|
||||||
|
|
||||||
override fun getCurrentId(): Int? {
|
override fun getCurrentId(): Int? {
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -29,6 +29,7 @@ class RepoLinkGenerator(
|
||||||
}
|
}
|
||||||
|
|
||||||
override val hasCache = true
|
override val hasCache = true
|
||||||
|
override val canSkipLoading = true
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
return currentIndex < episodes.size - 1
|
return currentIndex < episodes.size - 1
|
||||||
|
|
Loading…
Reference in a new issue