From 3e2836f4629f0150aeba14115c0d6beffc46eb0f Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sun, 25 Jul 2021 22:50:16 +0200 Subject: [PATCH] range and download fix --- .../com/lagradost/cloudstream3/UIHelper.kt | 2 +- .../animeproviders/ShiroProvider.kt | 7 +- .../cloudstream3/ui/result/EpisodeAdapter.kt | 2 +- .../cloudstream3/ui/result/ResultFragment.kt | 116 +++++++++++------- .../cloudstream3/ui/result/ResultViewModel.kt | 58 ++++++++- app/src/main/res/layout/fragment_result.xml | 28 ++++- 6 files changed, 153 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt index ba15dd67..e0af59db 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt @@ -419,7 +419,7 @@ object UIHelper { /**id, string */ @SuppressLint("RestrictedApi") - fun View.popupMenuNoIconsAndNoStringres( + fun View.popupMenuNoIconsAndNoStringRes( items: List>, onMenuItemClick: MenuItem.() -> Unit, ): PopupMenu { diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt index 9397e122..09f02427 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt @@ -211,8 +211,11 @@ class ShiroProvider : MainAPI() { val mapped = response.let { mapper.readValue(it.text) } val data = mapped.data val isDubbed = data.language == "dubbed" - val episodes = ArrayList(data.episodes?.map { AnimeEpisode(it.videos[0].video_id) } - ?: ArrayList()) + val episodes = + ArrayList( + data.episodes?.distinctBy { it.episode_number }?.sortedBy { it.episode_number } + ?.map { AnimeEpisode(it.videos[0].video_id) } + ?: ArrayList()) val status = when (data.status) { "current" -> ShowStatus.Ongoing "finished" -> ShowStatus.Completed diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index 34f1040f..ee412963 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -51,7 +51,7 @@ class EpisodeAdapter( @LayoutRes private var layout: Int = 0 fun updateLayout() { - layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2) + layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2f) // If over half has posters then use the large layout R.layout.result_episode_large else R.layout.result_episode } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index bcdfc411..4161f49c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -43,14 +43,13 @@ 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 +import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringRes import com.lagradost.cloudstream3.UIHelper.requestRW import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick -import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.setUpButton import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.setUpMaterialButton import com.lagradost.cloudstream3.ui.player.PlayerData import com.lagradost.cloudstream3.ui.player.PlayerFragment @@ -206,6 +205,7 @@ class ResultFragment : Fragment() { private var currentPoster: String? = null private var currentId: Int? = null private var currentIsMovie: Boolean? = null + private var episodeRanges: List? = null var url: String? = null @@ -666,8 +666,6 @@ class ResultFragment : Fragment() { allEpisodesSubs = it } - - observe(viewModel.selectedSeason) { season -> result_season_button?.text = fromIndexToSeasonText(season) } @@ -675,7 +673,7 @@ class ResultFragment : Fragment() { observe(viewModel.seasonSelections) { seasonList -> result_season_button?.visibility = if (seasonList.size <= 1) GONE else VISIBLE result_season_button?.setOnClickListener { - result_season_button?.popupMenuNoIconsAndNoStringres( + result_season_button?.popupMenuNoIconsAndNoStringRes( items = seasonList .map { Pair(it ?: -2, fromIndexToSeasonText(it)) }, ) { @@ -689,7 +687,6 @@ class ResultFragment : Fragment() { observe(viewModel.publicEpisodes) { episodes -> if (result_episodes == null || result_episodes.adapter == null) return@observe - result_episodes_text.text = "${episodes.size} Episode${if (episodes.size == 1) "" else "s"}" currentEpisodes = episodes activity?.runOnUiThread { (result_episodes.adapter as EpisodeAdapter).cardList = episodes @@ -698,6 +695,28 @@ class ResultFragment : Fragment() { } } + observe(viewModel.selectedRange) { range -> + result_episode_select?.text = range + } + + observe(viewModel.rangeOptions) { range -> + episodeRanges = range + result_episode_select?.visibility = if (range.size <= 1) GONE else VISIBLE + } + + result_episode_select.setOnClickListener { + val ranges = episodeRanges + if (ranges != null) { + it.popupMenuNoIconsAndNoStringRes(ranges.mapIndexed { index, s -> Pair(index, s) }.toList()) { + viewModel.changeRange(requireContext(), itemId) + } + } + } + + observe(viewModel.publicEpisodesCount) { count -> + result_episodes_text.text = "$count Episode${if (count == 1) "" else "s"}" + } + observe(viewModel.id) { currentId = it } @@ -820,6 +839,7 @@ class ResultFragment : Fragment() { } if (d.type == TvType.Movie && d is MovieLoadResponse) { + val hasDownloadSupport = api.hasDownloadSupport result_movie_parent.visibility = VISIBLE result_episodes_text.visibility = GONE result_episodes.visibility = GONE @@ -835,54 +855,58 @@ class ResultFragment : Fragment() { return@setOnLongClickListener true } + // result_options.setOnClickListener { // val card = currentEpisodes?.first() ?: return@setOnClickListener // handleAction(EpisodeClickEvent(ACTION_SHOW_OPTIONS, card)) // } - val localId = d.getId() - val file = - VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), localId) + result_download_movie.visibility = if (hasDownloadSupport) VISIBLE else GONE + if (hasDownloadSupport) { + val localId = d.getId() + val file = + VideoDownloadManager.getDownloadFileInfoAndUpdateSettings(requireContext(), localId) - setUpMaterialButton( - file?.fileLength, - file?.totalBytes, - result_movie_progress_downloaded, - result_download_movie, - result_movie_text_progress, - VideoDownloadHelper.DownloadEpisodeCached( - d.name, - d.posterUrl, - 0, - null, - localId, - localId, - d.rating, - d.plot - ) - ) { downloadClickEvent -> - if (downloadClickEvent.action == DOWNLOAD_ACTION_DOWNLOAD) { - handleAction( - EpisodeClickEvent( - ACTION_DOWNLOAD_EPISODE, - ResultEpisode( - d.name, - null, - 0, - null, - d.dataUrl, - d.apiName, - localId, - 0, - 0L, - 0L, - null, - null + setUpMaterialButton( + file?.fileLength, + file?.totalBytes, + result_movie_progress_downloaded, + result_download_movie, + result_movie_text_progress, + VideoDownloadHelper.DownloadEpisodeCached( + d.name, + d.posterUrl, + 0, + null, + localId, + localId, + d.rating, + d.plot + ) + ) { downloadClickEvent -> + if (downloadClickEvent.action == DOWNLOAD_ACTION_DOWNLOAD) { + handleAction( + EpisodeClickEvent( + ACTION_DOWNLOAD_EPISODE, + ResultEpisode( + d.name, + null, + 0, + null, + d.dataUrl, + d.apiName, + localId, + 0, + 0L, + 0L, + null, + null + ) ) ) - ) - } else { - handleDownloadClick(activity, currentHeaderName, downloadClickEvent) + } else { + handleDownloadClick(activity, currentHeaderName, downloadClickEvent) + } } } } else { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt index ba1d07b5..a6071035 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -16,13 +16,23 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState import com.lagradost.cloudstream3.utils.ExtractorLink import kotlinx.coroutines.launch +const val EPISODE_RANGE_SIZE = 50 +const val EPISODE_RANGE_OVERLOAD = 60 + class ResultViewModel : ViewModel() { private val _resultResponse: MutableLiveData> = MutableLiveData() private val _episodes: MutableLiveData> = MutableLiveData() private val _publicEpisodes: MutableLiveData> = MutableLiveData() + private val _publicEpisodesCount: MutableLiveData = MutableLiveData() // before the sorting + private val _rangeOptions: MutableLiveData> = MutableLiveData() + val selectedRange: MutableLiveData = MutableLiveData() + private val selectedRangeInt: MutableLiveData = MutableLiveData() + val rangeOptions: LiveData> = _rangeOptions + val resultResponse: LiveData> get() = _resultResponse val episodes: LiveData> get() = _episodes val publicEpisodes: LiveData> get() = _publicEpisodes + val publicEpisodesCount: LiveData get() = _publicEpisodesCount private val dubStatus: MutableLiveData = MutableLiveData() @@ -46,7 +56,7 @@ class ResultViewModel : ViewModel() { _watchStatus.postValue(currentWatch) } - private fun filterEpisodes(context: Context, list: List?, selection: Int?) { + private fun filterEpisodes(context: Context, list: List?, selection: Int?, range: Int?) { if (list == null) return val seasonTypes = HashMap() for (i in list) { @@ -62,11 +72,51 @@ class ResultViewModel : ViewModel() { if (internalId != null) context.setResultSeason(internalId, realSelection) selectedSeason.postValue(realSelection ?: -2) - _publicEpisodes.postValue(list.filter { it.season == realSelection }) + + var currentList = list.filter { it.season == realSelection } + _publicEpisodesCount.postValue(currentList.size) + + val rangeList = ArrayList() + for (i in currentList.indices step EPISODE_RANGE_SIZE) { + if (i + EPISODE_RANGE_SIZE < currentList.size) { + rangeList.add("${i + 1}-${i + EPISODE_RANGE_SIZE}") + } else { + rangeList.add("${i + 1}-${currentList.size}") + } + } + _rangeOptions.postValue(rangeList) + + val cRange = range ?: if (selection != null) { + 0 + } else { + selectedRangeInt.value ?: 0 + } + + val realRange = if (cRange * EPISODE_RANGE_SIZE > currentList.size) { + currentList.size / EPISODE_RANGE_SIZE + } else { + cRange + } + + selectedRangeInt.postValue(realRange) + selectedRange.postValue(rangeList[realRange]) + + if (currentList.size > EPISODE_RANGE_OVERLOAD) { + currentList = currentList.subList( + realRange * EPISODE_RANGE_SIZE, + minOf(currentList.size, (realRange + 1) * EPISODE_RANGE_SIZE) + ) + } + + _publicEpisodes.postValue(currentList) } fun changeSeason(context: Context, selection: Int?) { - filterEpisodes(context, _episodes.value, selection) + filterEpisodes(context, _episodes.value, selection, null) + } + + fun changeRange(context: Context, range: Int?) { + filterEpisodes(context, _episodes.value, null, range) } private fun updateEpisodes(context: Context, localId: Int?, list: List, selection: Int?) { @@ -74,7 +124,7 @@ class ResultViewModel : ViewModel() { filterEpisodes( context, list, - if (selection == -1) context.getResultSeason(localId ?: id.value ?: return) else selection + if (selection == -1) context.getResultSeason(localId ?: id.value ?: return) else selection, null ) } diff --git a/app/src/main/res/layout/fragment_result.xml b/app/src/main/res/layout/fragment_result.xml index dff6a855..a6ba4671 100644 --- a/app/src/main/res/layout/fragment_result.xml +++ b/app/src/main/res/layout/fragment_result.xml @@ -191,7 +191,7 @@ android:layout_width="match_parent" android:layout_height="50dp"> @@ -345,7 +345,7 @@ android:max="100" android:layout_gravity="end|center_vertical" android:progress="0" - android:visibility="visible" + android:visibility="gone" tools:visibility="visible"/>