forked from recloudstream/cloudstream
episode options sff
This commit is contained in:
parent
bcc17171e5
commit
b5f913cc72
7 changed files with 285 additions and 134 deletions
|
@ -27,6 +27,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.gms.cast.framework.CastContext
|
||||
import com.google.android.gms.cast.framework.CastState
|
||||
import com.google.android.gms.common.ConnectionResult
|
||||
import com.google.android.gms.common.GoogleApiAvailability
|
||||
import com.lagradost.cloudstream3.ui.result.ResultFragment
|
||||
|
@ -151,6 +152,17 @@ object UIHelper {
|
|||
return isCastApiAvailable
|
||||
}
|
||||
|
||||
fun Context.isConnectedToChromecast(): Boolean {
|
||||
if (isCastApiAvailable()) {
|
||||
val castContext = CastContext.getSharedInstance(this)
|
||||
if (castContext.castState == CastState.CONNECTED) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
fun adjustAlpha(@ColorInt color: Int, factor: Float): Int {
|
||||
val alpha = (Color.alpha(color) * factor).roundToInt()
|
||||
val red = Color.red(color)
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.lagradost.cloudstream3.ui.result
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -9,6 +11,7 @@ import android.widget.ImageView
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.widget.ContentLoadingProgressBar
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
|
@ -16,15 +19,27 @@ import com.bumptech.glide.load.model.GlideUrl
|
|||
import com.google.android.gms.cast.framework.CastContext
|
||||
import com.google.android.gms.cast.framework.CastState
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.UIHelper.hideSystemUI
|
||||
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
||||
import com.lagradost.cloudstream3.utils.getId
|
||||
import kotlinx.android.synthetic.main.result_episode.view.episode_holder
|
||||
import kotlinx.android.synthetic.main.result_episode.view.episode_text
|
||||
import kotlinx.android.synthetic.main.result_episode_large.view.*
|
||||
|
||||
const val ACTION_RELOAD_EPISODE = 4
|
||||
const val ACTION_CHROME_CAST_EPISODE = 2
|
||||
const val ACTION_DOWNLOAD_EPISODE = 3
|
||||
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||
const val ACTION_PLAY_EPISODE_IN_EXTERNAL_PLAYER = 2
|
||||
const val ACTION_PLAY_EPISODE_IN_BROWSER = 3
|
||||
|
||||
const val ACTION_CHROME_CAST_EPISODE = 4
|
||||
const val ACTION_CHROME_CAST_MIRROR = 5
|
||||
|
||||
const val ACTION_DOWNLOAD_EPISODE = 6
|
||||
const val ACTION_DOWNLOAD_MIRROR = 7
|
||||
|
||||
const val ACTION_RELOAD_EPISODE = 8
|
||||
const val ACTION_COPY_LINK = 9
|
||||
|
||||
const val ACTION_SHOW_OPTIONS = 10
|
||||
|
||||
data class EpisodeClickEvent(val action: Int, val data: ResultEpisode)
|
||||
|
||||
|
@ -69,8 +84,6 @@ class EpisodeAdapter(
|
|||
itemView: View,
|
||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||
) : RecyclerView.ViewHolder(itemView) {
|
||||
//private val episodeViewPrecentage: View? = itemView.episode_view_procentage
|
||||
// private val episodeViewPercentageOff: View? = itemView.episode_view_procentage_off
|
||||
private val episodeText: TextView = itemView.episode_text
|
||||
private val episodeRating: TextView? = itemView.episode_rating
|
||||
private val episodeDescript: TextView? = itemView.episode_descript
|
||||
|
@ -78,8 +91,6 @@ class EpisodeAdapter(
|
|||
private val episodePoster: ImageView? = itemView.episode_poster
|
||||
private val episodeDownload: ImageView? = itemView.episode_download
|
||||
|
||||
// val episodeExtra: ImageView = itemView.episode_extra
|
||||
// private val episodePlay: ImageView = itemView.episode_play
|
||||
private val episodeHolder = itemView.episode_holder
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
|
@ -87,20 +98,7 @@ class EpisodeAdapter(
|
|||
val name = if (card.name == null) "Episode ${card.episode}" else "${card.episode}. ${card.name}"
|
||||
episodeText.text = name
|
||||
|
||||
fun setWidth(v: View, procentage: Float) {
|
||||
val param = LinearLayout.LayoutParams(
|
||||
v.layoutParams.width,
|
||||
v.layoutParams.height,
|
||||
procentage
|
||||
)
|
||||
v.layoutParams = param
|
||||
}
|
||||
|
||||
val watchProgress = card.getWatchProgress()
|
||||
/*if (episodeViewPrecentage != null && episodeViewPercentageOff != null) {
|
||||
setWidth(episodeViewPrecentage, watchProgress)
|
||||
setWidth(episodeViewPercentageOff, 1 - watchProgress)
|
||||
}*/
|
||||
|
||||
episodeProgress?.progress = (watchProgress * 50).toInt()
|
||||
episodeProgress?.visibility = if (watchProgress > 0.0f) View.VISIBLE else View.GONE
|
||||
|
@ -133,21 +131,18 @@ class EpisodeAdapter(
|
|||
|
||||
episodeHolder.setOnClickListener {
|
||||
episodeHolder.context?.let { ctx ->
|
||||
if (ctx.isCastApiAvailable()) {
|
||||
val castContext = CastContext.getSharedInstance(ctx)
|
||||
|
||||
if (castContext.castState == CastState.CONNECTED) {
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card))
|
||||
} else {
|
||||
// clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
|
||||
}
|
||||
if (ctx.isConnectedToChromecast()) {
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card))
|
||||
} else {
|
||||
// clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card)) //TODO REDO TO MAIN
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
episodeHolder.setOnLongClickListener {
|
||||
clickCallback.invoke(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card))
|
||||
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
|
||||
episodeDownload?.setOnClickListener {
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.lagradost.cloudstream3.UIHelper.colorFromAttribute
|
|||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
|
||||
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
||||
import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast
|
||||
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
|
||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
|
||||
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringres
|
||||
|
@ -43,14 +44,16 @@ import com.lagradost.cloudstream3.mvvm.observe
|
|||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerData
|
||||
import com.lagradost.cloudstream3.ui.player.PlayerFragment
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.CastHelper.startCast
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
||||
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import kotlinx.android.synthetic.main.fragment_result.*
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
|
||||
const val MAX_SYNO_LENGH = 300
|
||||
|
@ -134,6 +137,7 @@ class ResultFragment : Fragment() {
|
|||
private var currentLoadingCount = 0 // THIS IS USED TO PREVENT LATE EVENTS, AFTER DISMISS WAS CLICKED
|
||||
private lateinit var viewModel: ResultViewModel
|
||||
private var allEpisodes: HashMap<Int, ArrayList<ExtractorLink>> = HashMap()
|
||||
private var allEpisodesSubs: HashMap<Int, ArrayList<SubtitleFile>> = HashMap()
|
||||
private var currentHeaderName: String? = null
|
||||
private var currentType: TvType? = null
|
||||
private var currentEpisodes: List<ResultEpisode>? = null
|
||||
|
@ -188,6 +192,7 @@ class ResultFragment : Fragment() {
|
|||
}
|
||||
|
||||
private var currentPoster: String? = null
|
||||
private var currentId: Int? = null
|
||||
private var currentIsMovie: Boolean? = null
|
||||
|
||||
var url: String? = null
|
||||
|
@ -255,59 +260,126 @@ class ResultFragment : Fragment() {
|
|||
requireActivity().popCurrentPage()
|
||||
}
|
||||
|
||||
fun handleAction(episodeClick: EpisodeClickEvent) {
|
||||
fun handleAction(episodeClick: EpisodeClickEvent): Job = main {
|
||||
//val id = episodeClick.data.id
|
||||
val index = episodeClick.data.index
|
||||
val buildInPlayer = true
|
||||
currentLoadingCount++
|
||||
var currentLinks: ArrayList<ExtractorLink>? = null
|
||||
var currentSubs: ArrayList<SubtitleFile>? = null
|
||||
|
||||
suspend fun requireLinks(isCasting: Boolean = false): Boolean {
|
||||
val currentLinksTemp =
|
||||
if (allEpisodes.containsKey(episodeClick.data.id)) allEpisodes[episodeClick.data.id] else null
|
||||
val currentSubsTemp =
|
||||
if (allEpisodes.containsKey(episodeClick.data.id)) allEpisodes[episodeClick.data.id] else null
|
||||
if (currentLinksTemp != null && currentLinksTemp.size > 0) {
|
||||
currentLinks = currentLinksTemp
|
||||
return true
|
||||
}
|
||||
|
||||
val skipLoading = if (apiName != null) {
|
||||
getApiFromName(apiName).instantLinkLoading
|
||||
} else false
|
||||
|
||||
var loadingDialog: AlertDialog? = null
|
||||
val currentLoad = currentLoadingCount
|
||||
|
||||
if (!skipLoading) {
|
||||
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustomTransparent)
|
||||
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
builder.setView(customLayout)
|
||||
|
||||
loadingDialog = builder.create()
|
||||
|
||||
loadingDialog.show()
|
||||
loadingDialog.setOnDismissListener {
|
||||
currentLoadingCount++
|
||||
}
|
||||
}
|
||||
|
||||
val data = viewModel.loadEpisode(episodeClick.data, isCasting)
|
||||
if (currentLoadingCount != currentLoad) return false
|
||||
loadingDialog?.dismiss()
|
||||
|
||||
when (data) {
|
||||
is Resource.Success -> {
|
||||
currentLinks = data.value.links
|
||||
currentSubs = data.value.subs
|
||||
return true
|
||||
}
|
||||
is Resource.Failure -> {
|
||||
Toast.makeText(requireContext(), R.string.error_loading_links, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val isLoaded = when (episodeClick.action) {
|
||||
ACTION_PLAY_EPISODE_IN_PLAYER -> true
|
||||
ACTION_CHROME_CAST_EPISODE -> requireLinks(true)
|
||||
ACTION_CHROME_CAST_MIRROR -> requireLinks(true)
|
||||
else -> requireLinks()
|
||||
}
|
||||
if (!isLoaded) return@main // CANT LOAD
|
||||
|
||||
when (episodeClick.action) {
|
||||
ACTION_CHROME_CAST_EPISODE -> {
|
||||
val skipLoading = if (apiName != null) {
|
||||
getApiFromName(apiName).instantLinkLoading
|
||||
} else false
|
||||
|
||||
ACTION_SHOW_OPTIONS -> {
|
||||
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustom)
|
||||
var dialog: AlertDialog? = null
|
||||
val currentLoad = currentLoadingCount
|
||||
builder.setTitle(episodeClick.data.name)
|
||||
val options = requireContext().resources.getStringArray(R.array.episode_long_click_options)
|
||||
val optionsValues =
|
||||
requireContext().resources.getIntArray(R.array.episode_long_click_options_values)
|
||||
|
||||
if (!skipLoading) {
|
||||
val builder = AlertDialog.Builder(requireContext(), R.style.AlertDialogCustomTransparent)
|
||||
val customLayout = layoutInflater.inflate(R.layout.dialog_loading, null)
|
||||
builder.setView(customLayout)
|
||||
val verifiedOptions = ArrayList<String>()
|
||||
val verifiedOptionsValues = ArrayList<Int>()
|
||||
|
||||
dialog = builder.create()
|
||||
for (i in options.indices) {
|
||||
val opv = optionsValues[i]
|
||||
val op = options[i]
|
||||
|
||||
dialog.show()
|
||||
dialog.setOnDismissListener {
|
||||
currentLoadingCount++
|
||||
val isConnected = requireContext().isConnectedToChromecast()
|
||||
val add = when (opv) {
|
||||
ACTION_CHROME_CAST_EPISODE -> isConnected
|
||||
ACTION_CHROME_CAST_MIRROR -> isConnected
|
||||
else -> true
|
||||
}
|
||||
if (add) {
|
||||
verifiedOptions.add(op)
|
||||
verifiedOptionsValues.add(opv)
|
||||
}
|
||||
}
|
||||
|
||||
// Toast.makeText(activity, "Loading links", Toast.LENGTH_SHORT).show()
|
||||
|
||||
viewModel.loadEpisode(episodeClick.data, true) { data ->
|
||||
if (currentLoadingCount != currentLoad) return@loadEpisode
|
||||
builder.setItems(
|
||||
verifiedOptions.toTypedArray()
|
||||
) { _, which ->
|
||||
handleAction(EpisodeClickEvent(verifiedOptionsValues[which], episodeClick.data))
|
||||
dialog?.dismiss()
|
||||
|
||||
when (data) {
|
||||
is Resource.Failure -> {
|
||||
Toast.makeText(activity, "Failed to load links", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
is Resource.Success -> {
|
||||
val eps = currentEpisodes ?: return@loadEpisode
|
||||
context?.startCast(
|
||||
apiName ?: return@loadEpisode,
|
||||
currentIsMovie ?: return@loadEpisode,
|
||||
currentHeaderName,
|
||||
currentPoster,
|
||||
episodeClick.data.index,
|
||||
eps,
|
||||
sortUrls(data.value.links),
|
||||
data.value.subs,
|
||||
startTime = episodeClick.data.getRealPosition(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog = builder.create()
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
|
||||
ACTION_CHROME_CAST_EPISODE -> {
|
||||
|
||||
val eps = currentEpisodes ?: return@main
|
||||
context?.startCast(
|
||||
apiName ?: return@main,
|
||||
currentIsMovie ?: return@main,
|
||||
currentHeaderName,
|
||||
currentPoster,
|
||||
episodeClick.data.index,
|
||||
eps,
|
||||
sortUrls(currentLinks ?: return@main),
|
||||
currentSubs ?: return@main,
|
||||
startTime = episodeClick.data.getRealPosition(),
|
||||
)
|
||||
}
|
||||
|
||||
ACTION_PLAY_EPISODE_IN_PLAYER -> {
|
||||
|
@ -330,60 +402,80 @@ class ResultFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
ACTION_RELOAD_EPISODE -> {
|
||||
/*viewModel.load(episodeClick.data) { res ->
|
||||
if (res is Resource.Success) {
|
||||
playEpisode(allEpisodes[id], index)
|
||||
}
|
||||
}*/
|
||||
viewModel.loadEpisode(episodeClick.data, false)
|
||||
}
|
||||
ACTION_DOWNLOAD_EPISODE -> {
|
||||
val tempUrl = url
|
||||
if (tempUrl != null) {
|
||||
viewModel.loadEpisode(episodeClick.data, true) { data ->
|
||||
if (data is Resource.Success) {
|
||||
val isMovie = currentIsMovie ?: return@loadEpisode
|
||||
val titleName = sanitizeFilename(currentHeaderName ?: return@loadEpisode)
|
||||
val meta = VideoDownloadManager.DownloadEpisodeMetadata(
|
||||
episodeClick.data.id,
|
||||
titleName,
|
||||
apiName ?: return@loadEpisode,
|
||||
episodeClick.data.poster ?: currentPoster,
|
||||
episodeClick.data.name,
|
||||
if (isMovie) null else episodeClick.data.season,
|
||||
if (isMovie) null else episodeClick.data.episode
|
||||
)
|
||||
val isMovie = currentIsMovie ?: return@main
|
||||
val titleName = sanitizeFilename(currentHeaderName ?: return@main)
|
||||
|
||||
val folder = when (currentType) {
|
||||
TvType.Anime -> "Anime/$titleName"
|
||||
TvType.Movie -> "Movies"
|
||||
TvType.TvSeries -> "TVSeries/$titleName"
|
||||
TvType.ONA -> "ONA"
|
||||
else -> null
|
||||
}
|
||||
val meta = VideoDownloadManager.DownloadEpisodeMetadata(
|
||||
episodeClick.data.id,
|
||||
titleName,
|
||||
apiName ?: return@main,
|
||||
episodeClick.data.poster ?: currentPoster,
|
||||
episodeClick.data.name,
|
||||
if (isMovie) null else episodeClick.data.season,
|
||||
if (isMovie) null else episodeClick.data.episode
|
||||
)
|
||||
|
||||
VideoDownloadManager.downloadEpisode(
|
||||
requireContext(),
|
||||
tempUrl,
|
||||
folder,
|
||||
meta,
|
||||
data.value.links
|
||||
)
|
||||
}
|
||||
}
|
||||
val folder = when (currentType) {
|
||||
TvType.Anime -> "Anime/$titleName"
|
||||
TvType.Movie -> "Movies"
|
||||
TvType.TvSeries -> "TVSeries/$titleName"
|
||||
TvType.ONA -> "ONA"
|
||||
else -> null
|
||||
}
|
||||
|
||||
context?.let { ctx ->
|
||||
// SET VISUAL KEYS
|
||||
ctx.setKey(
|
||||
DOWNLOAD_HEADER_CACHE, (currentId ?: return@let).toString(),
|
||||
VideoDownloadHelper.DownloadHeaderCached(
|
||||
apiName,
|
||||
url ?: return@let,
|
||||
currentType ?: return@let,
|
||||
currentHeaderName ?: return@let,
|
||||
currentPoster ?: return@let,
|
||||
currentId ?: return@let
|
||||
)
|
||||
)
|
||||
|
||||
val epData = episodeClick.data
|
||||
ctx.setKey(
|
||||
DOWNLOAD_EPISODE_CACHE,
|
||||
epData.id.toString(),
|
||||
VideoDownloadHelper.DownloadEpisodeCached(
|
||||
epData.name,
|
||||
epData.poster,
|
||||
epData.episode,
|
||||
epData.season,
|
||||
epData.id,
|
||||
currentId ?: return@let,
|
||||
epData.rating,
|
||||
epData.descript
|
||||
)
|
||||
)
|
||||
|
||||
// DOWNLOAD VIDEO
|
||||
VideoDownloadManager.downloadEpisode(
|
||||
ctx,
|
||||
url ?: return@main,
|
||||
folder,
|
||||
meta,
|
||||
currentLinks ?: return@main
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = activity?.let { it ->
|
||||
val adapter: RecyclerView.Adapter<RecyclerView.ViewHolder> =
|
||||
EpisodeAdapter(
|
||||
it,
|
||||
ArrayList(),
|
||||
result_episodes,
|
||||
) { episodeClick ->
|
||||
handleAction(episodeClick)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result_episodes.adapter = adapter
|
||||
result_episodes.layoutManager = GridLayoutManager(context, 1)
|
||||
|
@ -409,6 +501,12 @@ class ResultFragment : Fragment() {
|
|||
allEpisodes = it
|
||||
}
|
||||
|
||||
observe(viewModel.allEpisodesSubs) {
|
||||
allEpisodesSubs = it
|
||||
}
|
||||
|
||||
|
||||
|
||||
observe(viewModel.selectedSeason) { season ->
|
||||
result_season_button?.text = fromIndexToSeasonText(season)
|
||||
}
|
||||
|
@ -437,6 +535,10 @@ class ResultFragment : Fragment() {
|
|||
(result_episodes.adapter as EpisodeAdapter).notifyDataSetChanged()
|
||||
}
|
||||
|
||||
observe(viewModel.id) {
|
||||
currentId = it
|
||||
}
|
||||
|
||||
observe(viewModel.resultResponse) { data ->
|
||||
when (data) {
|
||||
is Resource.Success -> {
|
||||
|
|
|
@ -26,7 +26,7 @@ class ResultViewModel : ViewModel() {
|
|||
private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData()
|
||||
|
||||
private val page: MutableLiveData<LoadResponse> = MutableLiveData()
|
||||
private val id: MutableLiveData<Int> = MutableLiveData()
|
||||
val id: MutableLiveData<Int> = MutableLiveData()
|
||||
val selectedSeason: MutableLiveData<Int> = MutableLiveData(-2)
|
||||
val seasonSelections: MutableLiveData<List<Int?>> = MutableLiveData()
|
||||
|
||||
|
@ -208,6 +208,41 @@ class ResultViewModel : ViewModel() {
|
|||
loadEpisode(episode.id, episode.data, isCasting, callback)
|
||||
}
|
||||
|
||||
suspend fun loadEpisode(
|
||||
episode: ResultEpisode,
|
||||
isCasting: Boolean,
|
||||
) : Resource<ResultViewModel.EpisodeData> {
|
||||
return loadEpisode(episode.id, episode.data, isCasting)
|
||||
}
|
||||
|
||||
private suspend fun loadEpisode(
|
||||
id: Int,
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
): Resource<ResultViewModel.EpisodeData> {
|
||||
if (_allEpisodes.value?.contains(id) == true) {
|
||||
_allEpisodes.value?.remove(id)
|
||||
}
|
||||
val links = ArrayList<ExtractorLink>()
|
||||
val subs = ArrayList<SubtitleFile>()
|
||||
return safeApiCall {
|
||||
getApiFromName(_apiName.value).loadLinks(data, isCasting, { subtitleFile ->
|
||||
if (!subs.any { it.url == subtitleFile.url }) {
|
||||
subs.add(subtitleFile)
|
||||
_allEpisodesSubs.value?.set(id, subs)
|
||||
_allEpisodesSubs.postValue(_allEpisodesSubs.value)
|
||||
}
|
||||
}) { link ->
|
||||
if (!links.any { it.url == link.url }) {
|
||||
links.add(link)
|
||||
_allEpisodes.value?.set(id, links)
|
||||
_allEpisodes.postValue(_allEpisodes.value)
|
||||
}
|
||||
}
|
||||
EpisodeData(links, subs)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadEpisode(
|
||||
id: Int,
|
||||
data: String,
|
||||
|
@ -215,27 +250,7 @@ class ResultViewModel : ViewModel() {
|
|||
callback: (Resource<EpisodeData>) -> Unit,
|
||||
) =
|
||||
viewModelScope.launch {
|
||||
if (_allEpisodes.value?.contains(id) == true) {
|
||||
_allEpisodes.value?.remove(id)
|
||||
}
|
||||
val links = ArrayList<ExtractorLink>()
|
||||
val subs = ArrayList<SubtitleFile>()
|
||||
val localData = safeApiCall {
|
||||
getApiFromName(_apiName.value).loadLinks(data, isCasting, { subtitleFile ->
|
||||
if (!subs.any { it.url == subtitleFile.url }) {
|
||||
subs.add(subtitleFile)
|
||||
_allEpisodesSubs.value?.set(id, subs)
|
||||
_allEpisodesSubs.postValue(_allEpisodesSubs.value)
|
||||
}
|
||||
}) { link ->
|
||||
if (!links.any { it.url == link.url }) {
|
||||
links.add(link)
|
||||
_allEpisodes.value?.set(id, links)
|
||||
_allEpisodes.postValue(_allEpisodes.value)
|
||||
}
|
||||
}
|
||||
EpisodeData(links, subs)
|
||||
}
|
||||
val localData = loadEpisode(id, data, isCasting)
|
||||
callback.invoke(localData)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature
|
|||
import com.fasterxml.jackson.databind.json.JsonMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
|
||||
const val DOWNLOAD_HEADER_CACHE = "download_header_cache"
|
||||
const val DOWNLOAD_EPISODE_CACHE = "download_episode_cache"
|
||||
|
||||
const val PREFERENCES_NAME: String = "rebuild_preference"
|
||||
|
||||
object DataStore {
|
||||
|
|
|
@ -13,4 +13,27 @@
|
|||
<!-- Actually fake to make the skip op button the same style -->
|
||||
<item>@id/cast_button_type_forward_30_seconds</item>
|
||||
</array>
|
||||
|
||||
<array name="episode_long_click_options">
|
||||
<item>Chromecast Episode</item>
|
||||
<item>Chromecast Mirror</item>
|
||||
<item>Play In App</item>
|
||||
<item>Play In External App</item>
|
||||
<item>Play In Browser</item>
|
||||
<item>Copy Link</item>
|
||||
<item>Auto Download</item>
|
||||
<item>Download Mirror</item>
|
||||
<item>Reload Links</item>
|
||||
</array>
|
||||
<array name="episode_long_click_options_values">
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>9</item>
|
||||
<item>6</item>
|
||||
<item>7</item>
|
||||
<item>8</item>
|
||||
</array>
|
||||
</resources>
|
|
@ -39,4 +39,5 @@
|
|||
<string name="play_episode">Play Episode</string>
|
||||
<string name="need_storage">Allow to download episodes</string>
|
||||
<string name="download_descript">Download</string>
|
||||
<string name="error_loading_links">Error Loading Links</string>
|
||||
</resources>
|
Loading…
Reference in a new issue