range and download fix

This commit is contained in:
LagradOst 2021-07-25 22:50:16 +02:00
parent de149172bc
commit 3e2836f462
6 changed files with 153 additions and 60 deletions

View File

@ -419,7 +419,7 @@ object UIHelper {
/**id, string */
@SuppressLint("RestrictedApi")
fun View.popupMenuNoIconsAndNoStringres(
fun View.popupMenuNoIconsAndNoStringRes(
items: List<Pair<Int, String>>,
onMenuItemClick: MenuItem.() -> Unit,
): PopupMenu {

View File

@ -211,8 +211,11 @@ class ShiroProvider : MainAPI() {
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
val data = mapped.data
val isDubbed = data.language == "dubbed"
val episodes = ArrayList<AnimeEpisode>(data.episodes?.map { AnimeEpisode(it.videos[0].video_id) }
?: ArrayList<AnimeEpisode>())
val episodes =
ArrayList<AnimeEpisode>(
data.episodes?.distinctBy { it.episode_number }?.sortedBy { it.episode_number }
?.map { AnimeEpisode(it.videos[0].video_id) }
?: ArrayList<AnimeEpisode>())
val status = when (data.status) {
"current" -> ShowStatus.Ongoing
"finished" -> ShowStatus.Completed

View File

@ -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
}

View File

@ -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<String>? = 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 {

View File

@ -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<Resource<Any?>> = MutableLiveData()
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
private val _publicEpisodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
private val _publicEpisodesCount: MutableLiveData<Int> = MutableLiveData() // before the sorting
private val _rangeOptions: MutableLiveData<List<String>> = MutableLiveData()
val selectedRange: MutableLiveData<String> = MutableLiveData()
private val selectedRangeInt: MutableLiveData<Int> = MutableLiveData()
val rangeOptions: LiveData<List<String>> = _rangeOptions
val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse
val episodes: LiveData<List<ResultEpisode>> get() = _episodes
val publicEpisodes: LiveData<List<ResultEpisode>> get() = _publicEpisodes
val publicEpisodesCount: LiveData<Int> get() = _publicEpisodesCount
private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData()
@ -46,7 +56,7 @@ class ResultViewModel : ViewModel() {
_watchStatus.postValue(currentWatch)
}
private fun filterEpisodes(context: Context, list: List<ResultEpisode>?, selection: Int?) {
private fun filterEpisodes(context: Context, list: List<ResultEpisode>?, selection: Int?, range: Int?) {
if (list == null) return
val seasonTypes = HashMap<Int?, Boolean>()
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<String>()
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<ResultEpisode>, 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
)
}

View File

@ -191,7 +191,7 @@
android:layout_width="match_parent"
android:layout_height="50dp">
<com.google.android.material.button.MaterialButton
android:visibility="visible"
android:visibility="gone"
android:layout_gravity="center_vertical"
app:cornerRadius="4dp"
android:id="@+id/result_bookmark_button"
@ -202,7 +202,7 @@
app:iconTint="?attr/textColor"
android:textAllCaps="false"
app:icon="@drawable/ic_outline_remove_red_eye_24"
android:backgroundTint="@color/itemBackground"
android:backgroundTint="?attr/grayBackground"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
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"/>
<!--
<androidx.constraintlayout.widget.ConstraintLayout
@ -401,11 +401,27 @@
<com.google.android.material.button.MaterialButton
android:visibility="visible"
android:layout_gravity="center_vertical"
app:cornerRadius="4dp"
android:id="@+id/result_season_button"
tools:text="Subbed"
tools:text="Season 1"
app:rippleColor="?attr/bitDarkerGrayBackground"
app:rippleColor="?attr/grayBackground"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
android:backgroundTint="@color/itemBackground"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_marginEnd="10dp"
android:layout_height="50dp">
</com.google.android.material.button.MaterialButton>
<com.google.android.material.button.MaterialButton
android:visibility="visible"
android:layout_gravity="center_vertical"
android:id="@+id/result_episode_select"
tools:text="50-100"
app:rippleColor="?attr/grayBackground"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"