This commit is contained in:
LagradOst 2021-06-27 00:15:19 +02:00
parent 41d81a0c40
commit 2c312cd9b4
9 changed files with 155 additions and 39 deletions

View file

@ -354,4 +354,26 @@ object UIHelper {
popup.show()
return popup
}
inline fun View.popupMenuNoIconsAndNoStringres(
items: List<Pair<Int, String>>,
noinline onMenuItemClick: MenuItem.() -> Unit,
): PopupMenu {
val ctw = ContextThemeWrapper(context, R.style.PopupMenu)
val popup = PopupMenu(ctw, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0)
items.forEach { (id, stringRes) ->
popup.menu.add(0, id, 0, stringRes)
}
(popup.menu as? MenuBuilder)?.setOptionalIconsVisible(true)
popup.setOnMenuItemClickListener {
it.onMenuItemClick()
true
}
popup.show()
return popup
}
}

View file

@ -873,7 +873,6 @@ class PlayerFragment : Fragment() {
viewModel = ViewModelProvider(requireActivity()).get(ResultViewModel::class.java)
observeDirectly(viewModel.episodes) { _episodes ->
episodes = _episodes
if (isLoading) {
@ -1129,7 +1128,7 @@ class PlayerFragment : Fragment() {
changeSkip()
// initPlayer()
// initPlayer()
}
private fun getCurrentUrl(): ExtractorLink? {

View file

@ -89,7 +89,8 @@ class EpisodeAdapter(
@SuppressLint("SetTextI18n")
fun bind(card: ResultEpisode) {
episodeText.text = card.name ?: "Episode ${card.episode}"
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(
@ -125,7 +126,7 @@ class EpisodeAdapter(
}
if (card.rating != null) {
episodeRating?.text = "%.1f".format(card.rating.toFloat() / 10f).replace(",", ".")
episodeRating?.text = "Rated: %.1f".format(card.rating.toFloat() / 10f).replace(",", ".")
} else {
episodeRating?.text = ""
}

View file

@ -5,8 +5,6 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.view.LayoutInflater
import android.view.View
@ -39,6 +37,7 @@ import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
import com.lagradost.cloudstream3.UIHelper.popCurrentPage
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIcons
import com.lagradost.cloudstream3.UIHelper.popupMenuNoIconsAndNoStringres
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.observe
import com.lagradost.cloudstream3.ui.WatchType
@ -191,6 +190,14 @@ class ResultFragment : Fragment() {
var url: String? = null
private fun fromIndexToSeasonText(selection: Int?): String {
return when (selection) {
null -> "No Season"
-2 -> "No Season"
else -> "Season $selection"
}
}
@SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@ -358,7 +365,26 @@ class ResultFragment : Fragment() {
allEpisodes = it
}
observe(viewModel.episodes) { episodes ->
observe(viewModel.selectedSeason) { season ->
result_season_button?.text = fromIndexToSeasonText(season)
}
observe(viewModel.seasonSelections) { seasonList ->
result_season_button?.visibility = if (seasonList.size <= 1) GONE else VISIBLE
result_season_button?.setOnClickListener {
result_season_button?.popupMenuNoIconsAndNoStringres(
items = seasonList
.map { Pair(it ?: -2, fromIndexToSeasonText(it)) },
) {
val id = this.itemId
context?.let {
viewModel.changeSeason(it, if (id == -2) null else id)
}
}
}
}
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

View file

@ -1,17 +1,16 @@
package com.lagradost.cloudstream3.ui.result
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.*
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getApiFromName
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.ui.WatchType
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultSeason
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
import com.lagradost.cloudstream3.utils.ExtractorLink
import kotlinx.coroutines.launch
@ -19,12 +18,17 @@ import kotlinx.coroutines.launch
class ResultViewModel : ViewModel() {
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
private val _publicEpisodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
val resultResponse: LiveData<Resource<Any?>> get() = _resultResponse
val episodes: LiveData<List<ResultEpisode>> get() = _episodes
val publicEpisodes: LiveData<List<ResultEpisode>> get() = _publicEpisodes
private val dubStatus: MutableLiveData<DubStatus> = MutableLiveData()
private val page: MutableLiveData<LoadResponse> = MutableLiveData()
private val id: MutableLiveData<Int> = MutableLiveData()
val selectedSeason: MutableLiveData<Int> = MutableLiveData(-2)
val seasonSelections: MutableLiveData<List<Int?>> = MutableLiveData()
private val _watchStatus: MutableLiveData<WatchType> = MutableLiveData()
val watchStatus: LiveData<WatchType> get() = _watchStatus
@ -41,13 +45,43 @@ class ResultViewModel : ViewModel() {
_watchStatus.postValue(currentWatch)
}
private fun filterEpisodes(context: Context, list: List<ResultEpisode>?, selection: Int?) {
if (list == null) return
val seasonTypes = HashMap<Int?, Boolean>()
for (i in list) {
if (!seasonTypes.containsKey(i.season)) {
seasonTypes[i.season] = true
}
}
val seasons = seasonTypes.toList().map { it.first }
seasonSelections.postValue(seasons)
val realSelection = if (!seasonTypes.containsKey(selection)) seasons[0] else selection
val internalId = id.value
if (internalId != null) context.setResultSeason(internalId, realSelection)
selectedSeason.postValue(realSelection ?: -2)
_publicEpisodes.postValue(list.filter { it.season == realSelection })
}
fun changeSeason(context: Context, selection: Int?) {
filterEpisodes(context, _episodes.value, selection)
}
private fun updateEpisodes(context: Context, localId: Int?, list: List<ResultEpisode>, selection: Int?) {
_episodes.postValue(list)
filterEpisodes(context,
list,
if (selection == -1) context.getResultSeason(localId ?: id.value ?: return) else selection)
}
fun reloadEpisodes(context: Context) {
val current = _episodes.value ?: return
val copy = current.map {
val posDur = context.getViewPos(it.id)
it.copy(position = posDur?.position ?: 0, duration = posDur?.duration ?: 0)
}
_episodes.postValue(copy)
updateEpisodes(context, null, copy, selectedSeason.value)
}
// THIS SHOULD AT LEAST CLEAN IT UP, SO APIS CAN SWITCH DOMAIN
@ -98,7 +132,7 @@ class ResultViewModel : ViewModel() {
i.descript,
))
}
_episodes.postValue(episodes)
updateEpisodes(context, mainId, episodes, -1)
}
}
@ -106,8 +140,8 @@ class ResultViewModel : ViewModel() {
val episodes = ArrayList<ResultEpisode>()
for ((index, i) in d.episodes.withIndex()) {
episodes.add(context.buildResultEpisode(
(i.name
?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
i.name,
//?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
i.posterUrl,
i.episode ?: (index + 1),
i.season,
@ -119,10 +153,10 @@ class ResultViewModel : ViewModel() {
i.descript
))
}
_episodes.postValue(episodes)
updateEpisodes(context, mainId, episodes, -1)
}
is MovieLoadResponse -> {
_episodes.postValue(arrayListOf(context.buildResultEpisode(
updateEpisodes(context, mainId, arrayListOf(context.buildResultEpisode(
null,
null,
0, null,
@ -132,7 +166,7 @@ class ResultViewModel : ViewModel() {
0,
null,
null,
)))
)), -1)
}
}
}

View file

@ -7,6 +7,7 @@ import com.lagradost.cloudstream3.utils.DataStore.setKey
const val VIDEO_POS_DUR = "video_pos_dur"
const val RESULT_WATCH_STATE = "result_watch_state"
const val RESULT_SEASON = "result_season"
data class PosDur(val position: Long, val duration: Long)
@ -30,4 +31,11 @@ object DataStoreHelper {
fun Context.getResultWatchState(id: Int): WatchType {
return WatchType.fromInternalId(getKey<Int>("$currentAccount/$RESULT_WATCH_STATE", id.toString(), null))
}
fun Context.getResultSeason(id: Int): Int {
return getKey("$currentAccount/$RESULT_SEASON", id.toString(), -1)!!
}
fun Context.setResultSeason(id: Int, value : Int?) {
return setKey("$currentAccount/$RESULT_SEASON", id.toString(), value)
}
}

View file

@ -183,15 +183,15 @@
android:id="@+id/result_bookmark_button"
tools:text="Bookmark"
app:rippleColor="?attr/colorPrimary"
app:rippleColor="?attr/bitDarkerGrayBackground"
android:textColor="?attr/textColor"
app:iconTint="?attr/textColor"
android:textAllCaps="false"
app:icon="@drawable/ic_outline_remove_red_eye_24"
android:backgroundTint="@color/transparent"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:backgroundTint="@color/itemBackground"
style="@style/Widget.MaterialComponents.Button"
android:layout_width="wrap_content"
android:layout_height="45dp">
android:layout_height="50dp">
</com.google.android.material.button.MaterialButton>
@ -294,19 +294,40 @@
android:layout_height="45dp">
</com.google.android.material.button.MaterialButton>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/result_episodes_text"
tools:text="8 Episodes"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
<LinearLayout android:orientation="horizontal" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
<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="Bookmark"
app:rippleColor="?attr/bitDarkerGrayBackground"
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>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/result_episodes_text"
tools:text="8 Episodes"
android:textSize="17sp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textStyle="normal"
android:textColor="?attr/textColor"
/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:layout_marginTop="10dp"
android:layout_marginTop="0dp"
android:paddingBottom="100dp"
tools:listitem="@layout/result_episode"
android:layout_width="match_parent"

View file

@ -9,7 +9,7 @@
app:cardBackgroundColor="@color/itemBackground"
android:id="@+id/episode_holder"
android:foreground="?android:attr/selectableItemBackgroundBorderless"
android:layout_marginBottom="5dp"
android:layout_marginBottom="10dp"
>
<LinearLayout
android:padding="10dp"
@ -20,8 +20,9 @@
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<!--app:cardCornerRadius="@dimen/roundedImageRadius"-->
<androidx.cardview.widget.CardView
app:cardCornerRadius="@dimen/roundedImageRadius"
android:layout_width="126dp"
android:layout_height="72dp"
>
@ -41,7 +42,10 @@
android:contentDescription="@string/play_episode">
</ImageView>
<androidx.core.widget.ContentLoadingProgressBar
android:layout_marginBottom="-1.5dp"
android:id="@+id/episode_progress"
android:progressTint="@color/colorPrimary"
android:progressBackgroundTint="@color/colorPrimary"
style="@android:style/Widget.Material.ProgressBar.Horizontal"
android:layout_width="match_parent"
tools:progress="50"
@ -58,13 +62,14 @@
<TextView
android:id="@+id/episode_text"
tools:text="1. Jobless"
android:textStyle="bold"
android:textColor="@color/textColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<TextView
android:id="@+id/episode_rating"
tools:text="8.8"
tools:text="Rated: 8.8"
android:textColor="@color/grayTextColor"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

View file

@ -10,9 +10,9 @@
<color name="colorAccent">#3b65f5</color> <!-- 818fff-->
<color name="darkBackground">#2B2C30</color> <!--0f0f10 0E0E10 303135 2B2C30-->
<color name="bitDarkerGrayBackground">#1C1C20</color> <!--191a1f 19181E 202125 1C1C20-->
<color name="bitDarkerGrayBackground">#111111</color> <!--1C1C20 191a1f 19181E 202125 1C1C20-->
<color name="grayBackground">#1C1C20</color> <!--141419 202125-->
<color name="itemBackground">#17171B</color> <!-- 17171B 1B1B20-->
<color name="itemBackground">#161616</color> <!-- 17171B 1B1B20-->
<color name="textColor">#e9eaee</color> <!--FFF-->
<color name="grayTextColor">#9ba0a4</color> <!-- 5e5f62-->