forked from recloudstream/cloudstream
sff
This commit is contained in:
parent
f0df8ec391
commit
41d81a0c40
7 changed files with 134 additions and 40 deletions
|
@ -193,7 +193,14 @@ fun LoadResponse?.isAnimeBased(): Boolean {
|
||||||
return (this.type == TvType.Anime || this.type == TvType.ONA) // && (this is AnimeLoadResponse)
|
return (this.type == TvType.Anime || this.type == TvType.ONA) // && (this is AnimeLoadResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AnimeEpisode(val url: String, val name: String? = null)
|
data class AnimeEpisode(
|
||||||
|
val url: String,
|
||||||
|
val name: String? = null,
|
||||||
|
val posterUrl: String? = null,
|
||||||
|
val date: String? = null,
|
||||||
|
val rating: Int? = null,
|
||||||
|
val descript: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
data class AnimeLoadResponse(
|
data class AnimeLoadResponse(
|
||||||
val engName: String?,
|
val engName: String?,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.ui.result
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -7,12 +8,19 @@ import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.core.widget.ContentLoadingProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
import com.google.android.gms.cast.framework.CastState
|
import com.google.android.gms.cast.framework.CastState
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
|
||||||
import kotlinx.android.synthetic.main.result_episode.view.*
|
import kotlinx.android.synthetic.main.result_episode.view.*
|
||||||
|
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_PLAY_EPISODE_IN_PLAYER = 1
|
const val ACTION_PLAY_EPISODE_IN_PLAYER = 1
|
||||||
const val ACTION_RELOAD_EPISODE = 4
|
const val ACTION_RELOAD_EPISODE = 4
|
||||||
|
@ -27,10 +35,21 @@ class EpisodeAdapter(
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
) :
|
) :
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
@LayoutRes
|
||||||
|
private var layout: Int = 0
|
||||||
|
fun updateLayout() {
|
||||||
|
layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2)
|
||||||
|
R.layout.result_episode_large
|
||||||
|
else R.layout.result_episode
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
/*val layout = if (cardList.filter { it.poster != null }.size >= cardList.size / 2)
|
||||||
|
R.layout.result_episode_large
|
||||||
|
else R.layout.result_episode*/
|
||||||
|
|
||||||
return CardViewHolder(
|
return CardViewHolder(
|
||||||
LayoutInflater.from(parent.context).inflate(R.layout.result_episode, parent, false),
|
LayoutInflater.from(parent.context).inflate(layout, parent, false),
|
||||||
activity,
|
activity,
|
||||||
resView,
|
resView,
|
||||||
clickCallback
|
clickCallback
|
||||||
|
@ -56,13 +75,19 @@ class EpisodeAdapter(
|
||||||
resView: RecyclerView,
|
resView: RecyclerView,
|
||||||
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
private val clickCallback: (EpisodeClickEvent) -> Unit,
|
||||||
) : RecyclerView.ViewHolder(itemView) {
|
) : RecyclerView.ViewHolder(itemView) {
|
||||||
private val episodeViewPrecentage: View = itemView.episode_view_procentage
|
private val episodeViewPrecentage: View? = itemView.episode_view_procentage
|
||||||
private val episodeViewPercentageOff: View = itemView.episode_view_procentage_off
|
private val episodeViewPercentageOff: View? = itemView.episode_view_procentage_off
|
||||||
private val episodeText: TextView = itemView.episode_text
|
private val episodeText: TextView = itemView.episode_text
|
||||||
val episodeExtra: ImageView = itemView.episode_extra
|
private val episodeRating: TextView? = itemView.episode_rating
|
||||||
private val episodePlay: ImageView = itemView.episode_play
|
private val episodeDescript: TextView? = itemView.episode_descript
|
||||||
|
private val episodeProgress: ContentLoadingProgressBar? = itemView.episode_progress
|
||||||
|
private val episodePoster: ImageView? = itemView.episode_poster
|
||||||
|
|
||||||
|
// val episodeExtra: ImageView = itemView.episode_extra
|
||||||
|
// private val episodePlay: ImageView = itemView.episode_play
|
||||||
private val episodeHolder = itemView.episode_holder
|
private val episodeHolder = itemView.episode_holder
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
fun bind(card: ResultEpisode) {
|
fun bind(card: ResultEpisode) {
|
||||||
episodeText.text = card.name ?: "Episode ${card.episode}"
|
episodeText.text = card.name ?: "Episode ${card.episode}"
|
||||||
|
|
||||||
|
@ -76,8 +101,41 @@ class EpisodeAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
val watchProgress = card.getWatchProgress()
|
val watchProgress = card.getWatchProgress()
|
||||||
setWidth(episodeViewPrecentage, watchProgress)
|
if (episodeViewPrecentage != null && episodeViewPercentageOff != null) {
|
||||||
setWidth(episodeViewPercentageOff, 1 - watchProgress)
|
setWidth(episodeViewPrecentage, watchProgress)
|
||||||
|
setWidth(episodeViewPercentageOff, 1 - watchProgress)
|
||||||
|
}
|
||||||
|
|
||||||
|
episodeProgress?.progress = (watchProgress * 50).toInt()
|
||||||
|
episodeProgress?.visibility = if (watchProgress > 0.0f) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
if (card.poster != null) {
|
||||||
|
episodePoster?.visibility = View.VISIBLE
|
||||||
|
if (episodePoster != null) {
|
||||||
|
val glideUrl =
|
||||||
|
GlideUrl(card.poster)
|
||||||
|
activity.let {
|
||||||
|
Glide.with(it)
|
||||||
|
.load(glideUrl)
|
||||||
|
.into(episodePoster)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
episodePoster?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card.rating != null) {
|
||||||
|
episodeRating?.text = "%.1f".format(card.rating.toFloat() / 10f).replace(",", ".")
|
||||||
|
} else {
|
||||||
|
episodeRating?.text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card.descript != null) {
|
||||||
|
episodeDescript?.visibility = View.VISIBLE
|
||||||
|
episodeDescript?.text = card.descript
|
||||||
|
} else {
|
||||||
|
episodeDescript?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
episodeHolder.setOnClickListener {
|
episodeHolder.setOnClickListener {
|
||||||
if (activity.isCastApiAvailable()) {
|
if (activity.isCastApiAvailable()) {
|
||||||
|
|
|
@ -64,6 +64,8 @@ data class ResultEpisode(
|
||||||
val index: Int,
|
val index: Int,
|
||||||
val position: Long, // time in MS
|
val position: Long, // time in MS
|
||||||
val duration: Long, // duration in MS
|
val duration: Long, // duration in MS
|
||||||
|
val rating: Int?,
|
||||||
|
val descript: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun ResultEpisode.getRealPosition(): Long {
|
fun ResultEpisode.getRealPosition(): Long {
|
||||||
|
@ -91,9 +93,12 @@ fun Context.buildResultEpisode(
|
||||||
apiName: String,
|
apiName: String,
|
||||||
id: Int,
|
id: Int,
|
||||||
index: Int,
|
index: Int,
|
||||||
|
rating: Int?,
|
||||||
|
descript: String?,
|
||||||
): ResultEpisode {
|
): ResultEpisode {
|
||||||
val posDur = getViewPos(id)
|
val posDur = getViewPos(id)
|
||||||
return ResultEpisode(name,
|
return ResultEpisode(
|
||||||
|
name,
|
||||||
poster,
|
poster,
|
||||||
episode,
|
episode,
|
||||||
season,
|
season,
|
||||||
|
@ -102,7 +107,10 @@ fun Context.buildResultEpisode(
|
||||||
id,
|
id,
|
||||||
index,
|
index,
|
||||||
posDur?.position ?: 0,
|
posDur?.position ?: 0,
|
||||||
posDur?.duration ?: 0)
|
posDur?.duration ?: 0,
|
||||||
|
rating,
|
||||||
|
descript,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ResultEpisode.getWatchProgress(): Float {
|
fun ResultEpisode.getWatchProgress(): Float {
|
||||||
|
@ -355,6 +363,7 @@ class ResultFragment : Fragment() {
|
||||||
result_episodes_text.text = "${episodes.size} Episode${if (episodes.size == 1) "" else "s"}"
|
result_episodes_text.text = "${episodes.size} Episode${if (episodes.size == 1) "" else "s"}"
|
||||||
currentEpisodes = episodes
|
currentEpisodes = episodes
|
||||||
(result_episodes.adapter as EpisodeAdapter).cardList = episodes
|
(result_episodes.adapter as EpisodeAdapter).cardList = episodes
|
||||||
|
(result_episodes.adapter as EpisodeAdapter).updateLayout()
|
||||||
(result_episodes.adapter as EpisodeAdapter).notifyDataSetChanged()
|
(result_episodes.adapter as EpisodeAdapter).notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,7 +409,7 @@ class ResultFragment : Fragment() {
|
||||||
if (d.year != null) metadataInfoArray.add(Pair("Year", d.year.toString()))
|
if (d.year != null) metadataInfoArray.add(Pair("Year", d.year.toString()))
|
||||||
val rating = d.rating
|
val rating = d.rating
|
||||||
if (rating != null) metadataInfoArray.add(Pair("Rating",
|
if (rating != null) metadataInfoArray.add(Pair("Rating",
|
||||||
"%.2f/10.0".format(rating.toFloat() / 10f).replace(",", ".")))
|
"%.1f/10.0".format(rating.toFloat() / 10f).replace(",", ".")))
|
||||||
val duration = d.duration
|
val duration = d.duration
|
||||||
if (duration != null) metadataInfoArray.add(Pair("Duration", duration))
|
if (duration != null) metadataInfoArray.add(Pair("Duration", duration))
|
||||||
|
|
||||||
|
|
|
@ -87,13 +87,15 @@ class ResultViewModel : ViewModel() {
|
||||||
for ((index, i) in dataList.withIndex()) {
|
for ((index, i) in dataList.withIndex()) {
|
||||||
episodes.add(context.buildResultEpisode(
|
episodes.add(context.buildResultEpisode(
|
||||||
i.name,
|
i.name,
|
||||||
null,
|
i.posterUrl,
|
||||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||||
null, // TODO FIX SEASON
|
null, // TODO FIX SEASON
|
||||||
i.url,
|
i.url,
|
||||||
apiName,
|
apiName,
|
||||||
(mainId + index + 1),
|
(mainId + index + 1),
|
||||||
index,
|
index,
|
||||||
|
i.rating,
|
||||||
|
i.descript,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_episodes.postValue(episodes)
|
_episodes.postValue(episodes)
|
||||||
|
@ -106,13 +108,15 @@ class ResultViewModel : ViewModel() {
|
||||||
episodes.add(context.buildResultEpisode(
|
episodes.add(context.buildResultEpisode(
|
||||||
(i.name
|
(i.name
|
||||||
?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
|
?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
|
||||||
null,
|
i.posterUrl,
|
||||||
i.episode ?: (index + 1),
|
i.episode ?: (index + 1),
|
||||||
i.season,
|
i.season,
|
||||||
i.data,
|
i.data,
|
||||||
apiName,
|
apiName,
|
||||||
(mainId + index + 1).hashCode(),
|
(mainId + index + 1).hashCode(),
|
||||||
index,
|
index,
|
||||||
|
i.rating,
|
||||||
|
i.descript
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_episodes.postValue(episodes)
|
_episodes.postValue(episodes)
|
||||||
|
@ -126,6 +130,8 @@ class ResultViewModel : ViewModel() {
|
||||||
d.apiName,
|
d.apiName,
|
||||||
(mainId + 1),
|
(mainId + 1),
|
||||||
0,
|
0,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
>
|
>
|
||||||
<FrameLayout android:layout_gravity="center_vertical" android:layout_width="match_parent"
|
<FrameLayout
|
||||||
android:layout_marginEnd="30dp"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_height="30dp">
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:layout_height="30dp">
|
||||||
<androidx.appcompat.widget.SearchView
|
<androidx.appcompat.widget.SearchView
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:id="@+id/main_search"
|
android:id="@+id/main_search"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
app:cardCornerRadius="@dimen/roundedImageRadius"
|
app:cardCornerRadius="@dimen/roundedImageRadius"
|
||||||
app:cardBackgroundColor="?attr/itemBackground"
|
app:cardBackgroundColor="@color/itemBackground"
|
||||||
android:id="@+id/episode_holder"
|
android:id="@+id/episode_holder"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
|
@ -16,9 +16,12 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<LinearLayout android:layout_width="match_parent" android:orientation="horizontal"
|
<LinearLayout
|
||||||
android:layout_height="wrap_content">
|
android:layout_width="match_parent"
|
||||||
<FrameLayout
|
android:orientation="horizontal"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
app:cardCornerRadius="@dimen/roundedImageRadius"
|
||||||
android:layout_width="126dp"
|
android:layout_width="126dp"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
>
|
>
|
||||||
|
@ -30,11 +33,12 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:contentDescription="@string/episode_poster">
|
android:contentDescription="@string/episode_poster">
|
||||||
</ImageView>
|
</ImageView>
|
||||||
<ImageView tools:src="@drawable/play_button"
|
<ImageView
|
||||||
android:layout_gravity="center"
|
android:src="@drawable/play_button"
|
||||||
android:layout_width="36dp"
|
android:layout_gravity="center"
|
||||||
android:layout_height="36dp"
|
android:layout_width="36dp"
|
||||||
android:contentDescription="@string/play_episode">
|
android:layout_height="36dp"
|
||||||
|
android:contentDescription="@string/play_episode">
|
||||||
</ImageView>
|
</ImageView>
|
||||||
<androidx.core.widget.ContentLoadingProgressBar
|
<androidx.core.widget.ContentLoadingProgressBar
|
||||||
android:id="@+id/episode_progress"
|
android:id="@+id/episode_progress"
|
||||||
|
@ -44,26 +48,34 @@
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:layout_height="5dp">
|
android:layout_height="5dp">
|
||||||
</androidx.core.widget.ContentLoadingProgressBar>
|
</androidx.core.widget.ContentLoadingProgressBar>
|
||||||
</FrameLayout>
|
</androidx.cardview.widget.CardView>
|
||||||
<LinearLayout android:layout_marginStart="10dp" android:orientation="vertical"
|
<LinearLayout
|
||||||
android:layout_gravity="center" android:layout_width="match_parent"
|
android:layout_marginStart="15dp"
|
||||||
android:layout_height="wrap_content">
|
android:orientation="vertical"
|
||||||
<TextView android:id="@+id/episode_text" tools:text="1. Jobless" android:textColor="?attr/textColor"
|
android:layout_gravity="center"
|
||||||
android:layout_width="wrap_content" android:layout_height="wrap_content">
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/episode_text"
|
||||||
|
tools:text="1. Jobless"
|
||||||
|
android:textColor="@color/textColor"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
</TextView>
|
</TextView>
|
||||||
<TextView android:id="@+id/episode_rating"
|
<TextView
|
||||||
tools:text="8.8"
|
android:id="@+id/episode_rating"
|
||||||
android:textColor="?attr/grayTextColor"
|
tools:text="8.8"
|
||||||
android:layout_width="wrap_content"
|
android:textColor="@color/grayTextColor"
|
||||||
android:layout_height="wrap_content">
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
</TextView>
|
</TextView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<TextView
|
<TextView
|
||||||
android:paddingTop="2.5dp"
|
android:paddingTop="10dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:id="@+id/episode_descript"
|
android:id="@+id/episode_descript"
|
||||||
android:textColor="?attr/grayTextColor"
|
android:textColor="@color/grayTextColor"
|
||||||
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. "
|
tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. "
|
||||||
android:layout_width="match_parent" android:layout_height="wrap_content">
|
android:layout_width="match_parent" android:layout_height="wrap_content">
|
||||||
</TextView>
|
</TextView>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<color name="darkBackground">#2B2C30</color> <!--0f0f10 0E0E10 303135 2B2C30-->
|
<color name="darkBackground">#2B2C30</color> <!--0f0f10 0E0E10 303135 2B2C30-->
|
||||||
<color name="bitDarkerGrayBackground">#1C1C20</color> <!--191a1f 19181E 202125 1C1C20-->
|
<color name="bitDarkerGrayBackground">#1C1C20</color> <!--191a1f 19181E 202125 1C1C20-->
|
||||||
<color name="grayBackground">#1C1C20</color> <!--141419 202125-->
|
<color name="grayBackground">#1C1C20</color> <!--141419 202125-->
|
||||||
<color name="itemBackground">#17171B</color> <!--1B1B20-->
|
<color name="itemBackground">#17171B</color> <!-- 17171B 1B1B20-->
|
||||||
|
|
||||||
<color name="textColor">#e9eaee</color> <!--FFF-->
|
<color name="textColor">#e9eaee</color> <!--FFF-->
|
||||||
<color name="grayTextColor">#9ba0a4</color> <!-- 5e5f62-->
|
<color name="grayTextColor">#9ba0a4</color> <!-- 5e5f62-->
|
||||||
|
|
Loading…
Reference in a new issue