mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
removed slug
This commit is contained in:
parent
9695c980d6
commit
891d9b717f
23 changed files with 223 additions and 158 deletions
|
@ -98,7 +98,7 @@ abstract class MainAPI {
|
|||
return null
|
||||
}
|
||||
|
||||
open fun load(slug: String): LoadResponse? {
|
||||
open fun load(url: String): LoadResponse? {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,6 @@ class HomePageList(
|
|||
interface SearchResponse {
|
||||
val name: String
|
||||
val url: String // PUBLIC URL FOR OPEN IN APP
|
||||
val slug: String // USED FOR INTERNAL DATA
|
||||
val apiName: String
|
||||
val type: TvType
|
||||
val posterUrl: String?
|
||||
|
@ -195,7 +194,6 @@ interface SearchResponse {
|
|||
data class AnimeSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
@ -211,7 +209,6 @@ data class AnimeSearchResponse(
|
|||
data class MovieSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
@ -222,7 +219,6 @@ data class MovieSearchResponse(
|
|||
data class TvSeriesSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val slug: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ class MainActivity : AppCompatActivity() {
|
|||
} else {
|
||||
for (api in apis) {
|
||||
if (str.startsWith(api.mainUrl)) {
|
||||
loadResult(str, str, api.name)
|
||||
loadResult(str, api.name)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,13 +84,12 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getIsMovie(href)) {
|
||||
MovieSearchResponse(
|
||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
||||
title, href, this.name, TvType.Movie, img, null
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
getSlug(href),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
img,
|
||||
|
@ -122,13 +121,12 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getIsMovie(href)) {
|
||||
MovieSearchResponse(
|
||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
||||
title, href, this.name, TvType.Movie, img, null
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
getSlug(href),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
img,
|
||||
|
@ -183,7 +181,8 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse {
|
||||
override fun load(url: String): LoadResponse {
|
||||
val slug = url.replace("$mainUrl/","")
|
||||
if (getIsMovie(slug)) {
|
||||
val realSlug = slug.replace("movies/", "")
|
||||
val episode = getAnimeEpisode(realSlug, true)
|
||||
|
|
|
@ -165,7 +165,6 @@ class ShiroProvider : MainAPI() {
|
|||
return@map AnimeSearchResponse(
|
||||
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
||||
"$mainUrl/anime/${data.slug}",
|
||||
data.slug,
|
||||
this.name,
|
||||
type,
|
||||
"https://cdn.shiro.is/${data.image}",
|
||||
|
@ -193,7 +192,6 @@ class ShiroProvider : MainAPI() {
|
|||
return AnimeSearchResponse(
|
||||
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
||||
"$mainUrl/anime/${data.slug}",
|
||||
data.slug,
|
||||
this.name,
|
||||
type,
|
||||
"https://cdn.shiro.is/${data.image}",
|
||||
|
@ -264,8 +262,9 @@ class ShiroProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse? {
|
||||
override fun load(url: String): LoadResponse? {
|
||||
if (!autoLoadToken()) return null
|
||||
val slug = url.replace("$mainUrl/anime/", "").replace("$mainUrl/", "")
|
||||
val rurl = "https://tapi.shiro.is/anime/slug/${slug}?token=${token}"
|
||||
val response = khttp.get(rurl, timeout = 120.0)
|
||||
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
|
||||
|
@ -286,7 +285,7 @@ class ShiroProvider : MainAPI() {
|
|||
data.english,
|
||||
data.japanese,
|
||||
data.name.replace("Dubbed", ""),//data.canonicalTitle ?: data.name.replace("Dubbed", ""),
|
||||
"$mainUrl/anime/${slug}",
|
||||
"$mainUrl/anime/${url}",
|
||||
this.name,
|
||||
getType(data.type ?: ""),
|
||||
"https://cdn.shiro.is/${data.image}",
|
||||
|
|
|
@ -54,10 +54,6 @@ class TenshiProvider : MainAPI() {
|
|||
return movies.contains(aniId)
|
||||
}
|
||||
|
||||
private fun getSlug(href: String): String {
|
||||
return href.replace("$mainUrl/anime/", "")
|
||||
}
|
||||
|
||||
private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> {
|
||||
val items = soup.select("ul.thumb > li > a")
|
||||
if (items.isEmpty()) return ArrayList()
|
||||
|
@ -70,13 +66,12 @@ class TenshiProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getIsMovie(href, true)) {
|
||||
MovieSearchResponse(
|
||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
||||
title, href, this.name, TvType.Movie, img, null
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
getSlug(href),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
img,
|
||||
|
@ -170,9 +165,7 @@ class TenshiProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse {
|
||||
val url = "$mainUrl/anime/${slug}"
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb"))
|
||||
val document = Jsoup.parse(response.text)
|
||||
|
||||
|
@ -213,7 +206,7 @@ class TenshiProvider : MainAPI() {
|
|||
englishTitle,
|
||||
japaneseTitle,
|
||||
canonicalTitle,
|
||||
"$mainUrl/anime/${slug}",
|
||||
url,
|
||||
this.name,
|
||||
TenshiProvider.getType(type ?: ""),
|
||||
poster,
|
||||
|
|
|
@ -25,11 +25,6 @@ class WcoProvider : MainAPI() {
|
|||
override val hasQuickSearch: Boolean
|
||||
get() = true
|
||||
|
||||
|
||||
private fun getSlug(href: String): String {
|
||||
return href.replace("$mainUrl/anime/", "").replace("/", "")
|
||||
}
|
||||
|
||||
private fun fixAnimeLink(url: String): String {
|
||||
val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex()
|
||||
val (aniId) = regex.find(url)!!.destructured
|
||||
|
@ -51,13 +46,12 @@ class WcoProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getType(type) == TvType.Movie) {
|
||||
MovieSearchResponse(
|
||||
title, href, getSlug(href), this.name, TvType.Movie, img, year
|
||||
title, href, this.name, TvType.Movie, img, year
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
getSlug(href),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
img,
|
||||
|
@ -113,13 +107,12 @@ class WcoProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (getType(type) == TvType.Movie) {
|
||||
MovieSearchResponse(
|
||||
title, href, getSlug(href), this.name, TvType.Movie, img, year
|
||||
title, href, this.name, TvType.Movie, img, year
|
||||
)
|
||||
} else {
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
getSlug(href),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
img,
|
||||
|
@ -136,9 +129,7 @@ class WcoProvider : MainAPI() {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse {
|
||||
val url = "$mainUrl/anime/${slug}"
|
||||
|
||||
override fun load(url: String): LoadResponse {
|
||||
val response = khttp.get(url, timeout = 120.0)
|
||||
val document = Jsoup.parse(response.text)
|
||||
|
||||
|
@ -174,7 +165,7 @@ class WcoProvider : MainAPI() {
|
|||
canonicalTitle,
|
||||
japaneseTitle,
|
||||
canonicalTitle,
|
||||
"$mainUrl/anime/${slug}",
|
||||
url,
|
||||
this.name,
|
||||
getType(type ?: ""),
|
||||
poster,
|
||||
|
|
|
@ -25,7 +25,7 @@ class HDMProvider : MainAPI() {
|
|||
val data = i.selectFirst("> div.item")
|
||||
val img = data.selectFirst("> img").attr("src")
|
||||
val name = data.selectFirst("> div.movie-details").text()
|
||||
returnValue.add(MovieSearchResponse(name, href, href, this.name, TvType.Movie, img, null))
|
||||
returnValue.add(MovieSearchResponse(name, href, this.name, TvType.Movie, img, null))
|
||||
}
|
||||
|
||||
return returnValue
|
||||
|
@ -54,8 +54,8 @@ class HDMProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse? {
|
||||
val response = khttp.get(slug)
|
||||
override fun load(url: String): LoadResponse? {
|
||||
val response = khttp.get(url)
|
||||
val document = Jsoup.parse(response.text)
|
||||
val title = document.selectFirst("h2.movieTitle").text()
|
||||
val poster = document.selectFirst("div.post-thumbnail > img").attr("src")
|
||||
|
@ -65,7 +65,7 @@ class HDMProvider : MainAPI() {
|
|||
val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null
|
||||
|
||||
return MovieLoadResponse(
|
||||
title, slug, this.name, TvType.Movie,
|
||||
title, url, this.name, TvType.Movie,
|
||||
"$mainUrl/src/player/?v=$data", poster, year, descript, null
|
||||
)
|
||||
}
|
||||
|
|
|
@ -80,7 +80,6 @@ class LookMovieProvider : MainAPI() {
|
|||
MovieSearchResponse(
|
||||
m.title,
|
||||
url,
|
||||
url,//m.slug,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
m.poster ?: m.backdrop,
|
||||
|
@ -97,7 +96,6 @@ class LookMovieProvider : MainAPI() {
|
|||
MovieSearchResponse(
|
||||
s.title,
|
||||
url,
|
||||
url,//s.slug,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
s.poster ?: s.backdrop,
|
||||
|
@ -129,11 +127,11 @@ class LookMovieProvider : MainAPI() {
|
|||
returnValue.add(
|
||||
if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
name, href, href, this.name, TvType.Movie, poster, year
|
||||
name, href, this.name, TvType.Movie, poster, year
|
||||
)
|
||||
} else
|
||||
TvSeriesSearchResponse(
|
||||
name, href, href, this.name, TvType.TvSeries, poster, year, null
|
||||
name, href, this.name, TvType.TvSeries, poster, year, null
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -196,10 +194,10 @@ class LookMovieProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse? {
|
||||
val response = khttp.get(slug)
|
||||
override fun load(url: String): LoadResponse? {
|
||||
val response = khttp.get(url)
|
||||
val document = Jsoup.parse(response.text)
|
||||
val isMovie = slug.contains("/movies/")
|
||||
val isMovie = url.contains("/movies/")
|
||||
|
||||
val watchHeader = document.selectFirst("div.watch-heading")
|
||||
val nameHeader = watchHeader.selectFirst("> h1.bd-hd")
|
||||
|
@ -214,7 +212,7 @@ class LookMovieProvider : MainAPI() {
|
|||
val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1)
|
||||
?.replace(" ", "")
|
||||
?: return null
|
||||
val realSlug = slug.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "")
|
||||
val realSlug = url.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "")
|
||||
val realUrl =
|
||||
"$mainUrl/api/v1/security/${if (isMovie) "movie" else "show"}-access?${if (isMovie) "id_movie=$id" else "slug=$realSlug"}&token=1&sk=&step=1"
|
||||
|
||||
|
@ -228,7 +226,7 @@ class LookMovieProvider : MainAPI() {
|
|||
)
|
||||
return MovieLoadResponse(
|
||||
title,
|
||||
slug,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
localData,
|
||||
|
@ -280,7 +278,7 @@ class LookMovieProvider : MainAPI() {
|
|||
|
||||
return TvSeriesLoadResponse(
|
||||
title,
|
||||
slug,
|
||||
url,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
ArrayList(episodes),
|
||||
|
|
|
@ -50,7 +50,6 @@ class MeloMovieProvider : MainAPI() {
|
|||
TvSeriesSearchResponse(
|
||||
i.title,
|
||||
currentUrl,
|
||||
currentUrl,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
currentPoster,
|
||||
|
@ -63,7 +62,6 @@ class MeloMovieProvider : MainAPI() {
|
|||
MovieSearchResponse(
|
||||
i.title,
|
||||
currentUrl,
|
||||
currentUrl,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
currentUrl,
|
||||
|
@ -116,8 +114,8 @@ class MeloMovieProvider : MainAPI() {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun load(slug: String): LoadResponse? {
|
||||
val response = khttp.get(slug).text
|
||||
override fun load(url: String): LoadResponse? {
|
||||
val response = khttp.get(url).text
|
||||
|
||||
//backdrop = imgurl
|
||||
fun findUsingRegex(src: String): String? {
|
||||
|
@ -137,7 +135,7 @@ class MeloMovieProvider : MainAPI() {
|
|||
val serialize = document.selectFirst("table.accordion__list")
|
||||
return MovieLoadResponse(
|
||||
title,
|
||||
slug,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
serializeData(serialize),
|
||||
|
@ -164,7 +162,7 @@ class MeloMovieProvider : MainAPI() {
|
|||
episodes.reverse()
|
||||
return TvSeriesLoadResponse(
|
||||
title,
|
||||
slug,
|
||||
url,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
episodes,
|
||||
|
|
|
@ -40,7 +40,6 @@ class TrailersToProvider : MainAPI() {
|
|||
return@mapNotNull if (isMovieType) MovieSearchResponse(
|
||||
name,
|
||||
href,
|
||||
href,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
|
@ -48,7 +47,6 @@ class TrailersToProvider : MainAPI() {
|
|||
) else TvSeriesSearchResponse(
|
||||
name,
|
||||
href,
|
||||
href,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
posterUrl,
|
||||
|
@ -84,9 +82,9 @@ class TrailersToProvider : MainAPI() {
|
|||
|
||||
returnValue.add(
|
||||
if (isTvShow) {
|
||||
TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null)
|
||||
TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null)
|
||||
} else {
|
||||
MovieSearchResponse(name, href, href, this.name, TvType.Movie, poster, year)
|
||||
MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -111,9 +109,9 @@ class TrailersToProvider : MainAPI() {
|
|||
|
||||
returnValue.add(
|
||||
if (isTvShow) {
|
||||
TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null)
|
||||
TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null)
|
||||
} else {
|
||||
MovieSearchResponse(name, href, href, this.name, TvType.Movie, poster, year)
|
||||
MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
class ErrorLoadingException(message: String) : Exception(message)
|
||||
|
||||
class APIRepository(val api: MainAPI) {
|
||||
val name : String get() = api.name
|
||||
val mainUrl : String get() = api.mainUrl
|
||||
val name: String get() = api.name
|
||||
val mainUrl: String get() = api.mainUrl
|
||||
|
||||
suspend fun load(url: String): Resource<LoadResponse> {
|
||||
return safeApiCall {
|
||||
api.load(url) ?: throw ErrorLoadingException("Error Loading")
|
||||
// remove suffix for some slugs to handle correctly
|
||||
api.load(url.removeSuffix("/")) ?: throw ErrorLoadingException("Error Loading")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -143,11 +143,10 @@ fun ResultEpisode.getWatchProgress(): Float {
|
|||
|
||||
class ResultFragment : Fragment() {
|
||||
companion object {
|
||||
fun newInstance(url: String, slug: String, apiName: String, startAction: Int = 0) =
|
||||
fun newInstance(url: String, apiName: String, startAction: Int = 0) =
|
||||
ResultFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString("url", url)
|
||||
putString("slug", slug)
|
||||
putString("apiName", apiName)
|
||||
putInt("startAction", startAction)
|
||||
}
|
||||
|
@ -257,7 +256,6 @@ class ResultFragment : Fragment() {
|
|||
// activity?.fixPaddingStatusbar(result_toolbar)
|
||||
|
||||
url = arguments?.getString("url")
|
||||
val slug = arguments?.getString("slug")
|
||||
val apiName = arguments?.getString("apiName") ?: return
|
||||
startAction = arguments?.getInt("startAction") ?: START_ACTION_NORMAL
|
||||
|
||||
|
@ -431,7 +429,6 @@ class ResultFragment : Fragment() {
|
|||
VideoDownloadHelper.DownloadHeaderCached(
|
||||
apiName,
|
||||
url ?: return@let,
|
||||
slug ?: return@let,
|
||||
currentType ?: return@let,
|
||||
currentHeaderName ?: return@let,
|
||||
currentPoster ?: return@let,
|
||||
|
@ -986,21 +983,20 @@ class ResultFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
if (apiName != null && slug != null) {
|
||||
val tempUrl = url
|
||||
if (tempUrl != null) {
|
||||
result_reload_connectionerror.setOnClickListener {
|
||||
viewModel.load(requireContext(), slug, apiName)
|
||||
viewModel.load(requireContext(), tempUrl, apiName)
|
||||
}
|
||||
|
||||
if (url != null) {
|
||||
result_reload_connection_open_in_browser.setOnClickListener {
|
||||
val i = Intent(ACTION_VIEW)
|
||||
i.data = Uri.parse(url)
|
||||
startActivity(i)
|
||||
}
|
||||
result_reload_connection_open_in_browser.setOnClickListener {
|
||||
val i = Intent(ACTION_VIEW)
|
||||
i.data = Uri.parse(tempUrl)
|
||||
startActivity(i)
|
||||
}
|
||||
|
||||
if (viewModel.resultResponse.value == null)
|
||||
viewModel.load(requireContext(), slug, apiName)
|
||||
viewModel.load(requireContext(), tempUrl, apiName)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,9 +9,11 @@ import com.lagradost.cloudstream3.mvvm.Resource
|
|||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.ui.APIRepository
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
|
||||
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.setBookmarkedData
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
@ -21,7 +23,7 @@ const val EPISODE_RANGE_SIZE = 50
|
|||
const val EPISODE_RANGE_OVERLOAD = 60
|
||||
|
||||
class ResultViewModel : ViewModel() {
|
||||
var repo : APIRepository? = null
|
||||
var repo: APIRepository? = null
|
||||
|
||||
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
||||
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
|
||||
|
@ -51,6 +53,21 @@ class ResultViewModel : ViewModel() {
|
|||
val currentId = id.value ?: return
|
||||
_watchStatus.postValue(status)
|
||||
context.setResultWatchState(currentId, status.internalId)
|
||||
val resultPage = page.value
|
||||
if (resultPage != null) {
|
||||
context.setBookmarkedData(
|
||||
currentId,
|
||||
DataStoreHelper.BookmarkedData(
|
||||
currentId,
|
||||
resultPage.name,
|
||||
resultPage.url,
|
||||
resultPage.apiName,
|
||||
resultPage.type,
|
||||
resultPage.posterUrl,
|
||||
resultPage.year
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadWatchStatus(context: Context, localId: Int? = null) {
|
||||
|
@ -154,80 +171,78 @@ class ResultViewModel : ViewModel() {
|
|||
when (data) {
|
||||
is Resource.Success -> {
|
||||
val d = data.value
|
||||
if (d is LoadResponse) {
|
||||
page.postValue(d)
|
||||
val mainId = d.getId()
|
||||
id.postValue(mainId)
|
||||
loadWatchStatus(context, mainId)
|
||||
page.postValue(d)
|
||||
val mainId = d.getId()
|
||||
id.postValue(mainId)
|
||||
loadWatchStatus(context, mainId)
|
||||
|
||||
when (d) {
|
||||
is AnimeLoadResponse -> {
|
||||
val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0
|
||||
dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed)
|
||||
when (d) {
|
||||
is AnimeLoadResponse -> {
|
||||
val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0
|
||||
dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed)
|
||||
|
||||
val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes)
|
||||
val dataList = (if (isDub) d.dubEpisodes else d.subEpisodes)
|
||||
|
||||
if (dataList != null) {
|
||||
val episodes = ArrayList<ResultEpisode>()
|
||||
for ((index, i) in dataList.withIndex()) {
|
||||
episodes.add(
|
||||
context.buildResultEpisode(
|
||||
i.name,
|
||||
i.posterUrl,
|
||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||
null, // TODO FIX SEASON
|
||||
i.url,
|
||||
apiName,
|
||||
(mainId + index + 1),
|
||||
index,
|
||||
i.rating,
|
||||
i.descript,
|
||||
)
|
||||
)
|
||||
}
|
||||
updateEpisodes(context, mainId, episodes, -1)
|
||||
}
|
||||
}
|
||||
|
||||
is TvSeriesLoadResponse -> {
|
||||
if (dataList != null) {
|
||||
val episodes = ArrayList<ResultEpisode>()
|
||||
for ((index, i) in d.episodes.withIndex()) {
|
||||
for ((index, i) in dataList.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.posterUrl,
|
||||
i.episode ?: (index + 1),
|
||||
i.season,
|
||||
i.data,
|
||||
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||
null, // TODO FIX SEASON
|
||||
i.url,
|
||||
apiName,
|
||||
(mainId + index + 1).hashCode(),
|
||||
(mainId + index + 1),
|
||||
index,
|
||||
i.rating,
|
||||
i.descript
|
||||
i.descript,
|
||||
)
|
||||
)
|
||||
}
|
||||
updateEpisodes(context, mainId, episodes, -1)
|
||||
}
|
||||
is MovieLoadResponse -> {
|
||||
updateEpisodes(
|
||||
context, mainId, arrayListOf(
|
||||
context.buildResultEpisode(
|
||||
d.name,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
d.dataUrl,
|
||||
d.apiName,
|
||||
(mainId), // HAS SAME ID
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
), -1
|
||||
}
|
||||
|
||||
is TvSeriesLoadResponse -> {
|
||||
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.posterUrl,
|
||||
i.episode ?: (index + 1),
|
||||
i.season,
|
||||
i.data,
|
||||
apiName,
|
||||
(mainId + index + 1).hashCode(),
|
||||
index,
|
||||
i.rating,
|
||||
i.descript
|
||||
)
|
||||
)
|
||||
}
|
||||
updateEpisodes(context, mainId, episodes, -1)
|
||||
}
|
||||
is MovieLoadResponse -> {
|
||||
updateEpisodes(
|
||||
context, mainId, arrayListOf(
|
||||
context.buildResultEpisode(
|
||||
d.name,
|
||||
null,
|
||||
0,
|
||||
null,
|
||||
d.dataUrl,
|
||||
d.apiName,
|
||||
(mainId), // HAS SAME ID
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
), -1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -303,8 +318,4 @@ class ResultViewModel : ViewModel() {
|
|||
val localData = loadEpisode(id, data, isCasting)
|
||||
callback.invoke(localData)
|
||||
}
|
||||
|
||||
fun loadIndex(index: Int): ResultEpisode? {
|
||||
return episodes.value?.get(index)
|
||||
}
|
||||
}
|
|
@ -142,7 +142,7 @@ class SearchFragment : Fragment() {
|
|||
search_loading_bar.alpha = 0f
|
||||
}
|
||||
is Resource.Failure -> {
|
||||
Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||
searchExitIcon.alpha = 1f
|
||||
search_loading_bar.alpha = 0f
|
||||
}
|
||||
|
|
|
@ -43,18 +43,18 @@ object AppUtils {
|
|||
}
|
||||
}
|
||||
|
||||
fun AppCompatActivity.loadResult(url: String, slug: String, apiName: String, startAction: Int = 0) {
|
||||
fun AppCompatActivity.loadResult(url: String, apiName: String, startAction: Int = 0) {
|
||||
this.runOnUiThread {
|
||||
viewModelStore.clear()
|
||||
this.supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
||||
.add(R.id.homeRoot, ResultFragment.newInstance(url, slug, apiName, startAction))
|
||||
.add(R.id.homeRoot, ResultFragment.newInstance(url, apiName, startAction))
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) {
|
||||
(this as AppCompatActivity?)?.loadResult(card.url, card.slug, card.apiName, startAction)
|
||||
(this as AppCompatActivity?)?.loadResult(card.url, card.apiName, startAction)
|
||||
}
|
||||
|
||||
fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) {
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
package com.lagradost.cloudstream3.utils
|
||||
|
||||
import android.content.Context
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
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_WATCH_STATE_DATA = "result_watch_state_data"
|
||||
const val RESULT_SEASON = "result_season"
|
||||
|
||||
|
||||
object DataStoreHelper {
|
||||
data class PosDur(val position: Long, val duration: Long)
|
||||
|
||||
fun PosDur.fixVisual(): PosDur {
|
||||
if (duration <= 0) return PosDur(0, duration)
|
||||
val percentage = position * 100 / duration
|
||||
|
@ -21,8 +25,28 @@ object DataStoreHelper {
|
|||
return this
|
||||
}
|
||||
|
||||
data class BookmarkedData(
|
||||
val parentId: Int,
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override val type: TvType,
|
||||
override val posterUrl: String?,
|
||||
override val year: Int?,
|
||||
) : SearchResponse
|
||||
|
||||
var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION
|
||||
|
||||
fun Context.setBookmarkedData(id: Int?, data: BookmarkedData) {
|
||||
if (id == null) return
|
||||
setKey("$currentAccount/$RESULT_WATCH_STATE", id.toString(), data)
|
||||
}
|
||||
|
||||
fun Context.getBookmarkedData(id: Int?): BookmarkedData? {
|
||||
if (id == null) return null
|
||||
return getKey("$currentAccount/$RESULT_WATCH_STATE", id.toString())
|
||||
}
|
||||
|
||||
fun Context.setViewPos(id: Int?, pos: Long, dur: Long) {
|
||||
if (id == null) return
|
||||
setKey("$currentAccount/$VIDEO_POS_DUR", id.toString(), PosDur(pos, dur))
|
||||
|
@ -44,7 +68,8 @@ object DataStoreHelper {
|
|||
fun Context.getResultSeason(id: Int): Int {
|
||||
return getKey("$currentAccount/$RESULT_SEASON", id.toString(), -1)!!
|
||||
}
|
||||
fun Context.setResultSeason(id: Int, value : Int?) {
|
||||
|
||||
fun Context.setResultSeason(id: Int, value: Int?) {
|
||||
return setKey("$currentAccount/$RESULT_SEASON", id.toString(), value)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package com.lagradost.cloudstream3.utils
|
|||
|
||||
import com.lagradost.cloudstream3.extractors.*
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.utils.extractors.*
|
||||
|
||||
data class ExtractorLink(
|
||||
val source: String,
|
||||
|
|
|
@ -17,7 +17,6 @@ object VideoDownloadHelper {
|
|||
data class DownloadHeaderCached(
|
||||
val apiName: String,
|
||||
val url: String,
|
||||
val slug : String,
|
||||
val type : TvType,
|
||||
val name: String,
|
||||
val poster: String?,
|
||||
|
|
5
app/src/main/res/drawable/ic_baseline_filter_list_24.xml
Normal file
5
app/src/main/res/drawable/ic_baseline_filter_list_24.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
|
||||
</vector>
|
|
@ -87,6 +87,7 @@
|
|||
android:id="@+id/home_loaded"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -202,6 +203,57 @@
|
|||
</ImageView>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_bookmarked_holder"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<FrameLayout
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:id="@+id/home_bookmarked_child_more_info"
|
||||
android:padding="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<ImageView
|
||||
android:src="@drawable/ic_baseline_filter_list_24"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:contentDescription="@string/filter_bookmarks">
|
||||
</ImageView>
|
||||
<TextView
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="40dp"
|
||||
android:id="@+id/home_bookmarked_parent_item_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="?attr/textColor"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:text="Bookmarked"
|
||||
/>
|
||||
<ImageView
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:src="@drawable/ic_baseline_arrow_forward_24"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/home_more_info">
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
android:id="@+id/home_bookmarked_child_recyclerview"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:listitem="@layout/home_result_grid"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/home_master_recycler"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -210,5 +262,4 @@
|
|||
/>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</FrameLayout>
|
|
@ -108,6 +108,7 @@
|
|||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:visibility="gone"
|
||||
android:alpha="0"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/result_poster_blur_holder"
|
||||
|
@ -120,10 +121,13 @@
|
|||
tools:src="@drawable/example_poster"
|
||||
android:background="@color/darkBackground"
|
||||
android:id="@+id/result_poster_blur"
|
||||
android:contentDescription=""/>
|
||||
<ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom"
|
||||
android:layout_width="match_parent" android:layout_height="30dp">
|
||||
|
||||
android:contentDescription="@string/background_blur"/>
|
||||
<ImageView
|
||||
android:src="@drawable/background_shadow"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:contentDescription="@string/background_shadow">
|
||||
</ImageView>
|
||||
</FrameLayout>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
|
@ -163,13 +167,13 @@
|
|||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_marginRight="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
tools:text="The Perfect Run The Perfect Run The Perfect Run"
|
||||
android:id="@+id/result_title"
|
||||
android:textSize="20sp"
|
||||
|
@ -201,7 +205,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:cornerRadius="4dp"
|
||||
android:id="@+id/result_bookmark_button"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<FrameLayout
|
||||
|
@ -36,7 +36,7 @@
|
|||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
android:id="@+id/home_child_recyclerview"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:listitem="@layout/home_result_grid"
|
||||
/>
|
||||
|
|
|
@ -61,4 +61,7 @@
|
|||
<string name="home_info">Info</string>
|
||||
<string name="home_next_random">Next Random</string>
|
||||
<string name="home_change_provider">Change Provider</string>
|
||||
<string name="background_blur">Background blur</string>
|
||||
<string name="background_shadow">Background Shadow</string>
|
||||
<string name="filter_bookmarks">Filter Bookmarks</string>
|
||||
</resources>
|
Loading…
Reference in a new issue