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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun load(slug: String): LoadResponse? {
|
open fun load(url: String): LoadResponse? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,6 @@ class HomePageList(
|
||||||
interface SearchResponse {
|
interface SearchResponse {
|
||||||
val name: String
|
val name: String
|
||||||
val url: String // PUBLIC URL FOR OPEN IN APP
|
val url: String // PUBLIC URL FOR OPEN IN APP
|
||||||
val slug: String // USED FOR INTERNAL DATA
|
|
||||||
val apiName: String
|
val apiName: String
|
||||||
val type: TvType
|
val type: TvType
|
||||||
val posterUrl: String?
|
val posterUrl: String?
|
||||||
|
@ -195,7 +194,6 @@ interface SearchResponse {
|
||||||
data class AnimeSearchResponse(
|
data class AnimeSearchResponse(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val slug: String,
|
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override val type: TvType,
|
override val type: TvType,
|
||||||
|
|
||||||
|
@ -211,7 +209,6 @@ data class AnimeSearchResponse(
|
||||||
data class MovieSearchResponse(
|
data class MovieSearchResponse(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val slug: String,
|
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override val type: TvType,
|
override val type: TvType,
|
||||||
|
|
||||||
|
@ -222,7 +219,6 @@ data class MovieSearchResponse(
|
||||||
data class TvSeriesSearchResponse(
|
data class TvSeriesSearchResponse(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val slug: String,
|
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
override val type: TvType,
|
override val type: TvType,
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
} else {
|
} else {
|
||||||
for (api in apis) {
|
for (api in apis) {
|
||||||
if (str.startsWith(api.mainUrl)) {
|
if (str.startsWith(api.mainUrl)) {
|
||||||
loadResult(str, str, api.name)
|
loadResult(str, api.name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,13 +84,12 @@ class DubbedAnimeProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (getIsMovie(href)) {
|
if (getIsMovie(href)) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
title, href, this.name, TvType.Movie, img, null
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
title,
|
title,
|
||||||
href,
|
href,
|
||||||
getSlug(href),
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Anime,
|
TvType.Anime,
|
||||||
img,
|
img,
|
||||||
|
@ -122,13 +121,12 @@ class DubbedAnimeProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (getIsMovie(href)) {
|
if (getIsMovie(href)) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
title, href, this.name, TvType.Movie, img, null
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
title,
|
title,
|
||||||
href,
|
href,
|
||||||
getSlug(href),
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Anime,
|
TvType.Anime,
|
||||||
img,
|
img,
|
||||||
|
@ -183,7 +181,8 @@ class DubbedAnimeProvider : MainAPI() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse {
|
override fun load(url: String): LoadResponse {
|
||||||
|
val slug = url.replace("$mainUrl/","")
|
||||||
if (getIsMovie(slug)) {
|
if (getIsMovie(slug)) {
|
||||||
val realSlug = slug.replace("movies/", "")
|
val realSlug = slug.replace("movies/", "")
|
||||||
val episode = getAnimeEpisode(realSlug, true)
|
val episode = getAnimeEpisode(realSlug, true)
|
||||||
|
|
|
@ -165,7 +165,6 @@ class ShiroProvider : MainAPI() {
|
||||||
return@map AnimeSearchResponse(
|
return@map AnimeSearchResponse(
|
||||||
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
||||||
"$mainUrl/anime/${data.slug}",
|
"$mainUrl/anime/${data.slug}",
|
||||||
data.slug,
|
|
||||||
this.name,
|
this.name,
|
||||||
type,
|
type,
|
||||||
"https://cdn.shiro.is/${data.image}",
|
"https://cdn.shiro.is/${data.image}",
|
||||||
|
@ -193,7 +192,6 @@ class ShiroProvider : MainAPI() {
|
||||||
return AnimeSearchResponse(
|
return AnimeSearchResponse(
|
||||||
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
|
||||||
"$mainUrl/anime/${data.slug}",
|
"$mainUrl/anime/${data.slug}",
|
||||||
data.slug,
|
|
||||||
this.name,
|
this.name,
|
||||||
type,
|
type,
|
||||||
"https://cdn.shiro.is/${data.image}",
|
"https://cdn.shiro.is/${data.image}",
|
||||||
|
@ -264,8 +262,9 @@ class ShiroProvider : MainAPI() {
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse? {
|
override fun load(url: String): LoadResponse? {
|
||||||
if (!autoLoadToken()) return null
|
if (!autoLoadToken()) return null
|
||||||
|
val slug = url.replace("$mainUrl/anime/", "").replace("$mainUrl/", "")
|
||||||
val rurl = "https://tapi.shiro.is/anime/slug/${slug}?token=${token}"
|
val rurl = "https://tapi.shiro.is/anime/slug/${slug}?token=${token}"
|
||||||
val response = khttp.get(rurl, timeout = 120.0)
|
val response = khttp.get(rurl, timeout = 120.0)
|
||||||
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
|
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
|
||||||
|
@ -286,7 +285,7 @@ class ShiroProvider : MainAPI() {
|
||||||
data.english,
|
data.english,
|
||||||
data.japanese,
|
data.japanese,
|
||||||
data.name.replace("Dubbed", ""),//data.canonicalTitle ?: data.name.replace("Dubbed", ""),
|
data.name.replace("Dubbed", ""),//data.canonicalTitle ?: data.name.replace("Dubbed", ""),
|
||||||
"$mainUrl/anime/${slug}",
|
"$mainUrl/anime/${url}",
|
||||||
this.name,
|
this.name,
|
||||||
getType(data.type ?: ""),
|
getType(data.type ?: ""),
|
||||||
"https://cdn.shiro.is/${data.image}",
|
"https://cdn.shiro.is/${data.image}",
|
||||||
|
|
|
@ -54,10 +54,6 @@ class TenshiProvider : MainAPI() {
|
||||||
return movies.contains(aniId)
|
return movies.contains(aniId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSlug(href: String): String {
|
|
||||||
return href.replace("$mainUrl/anime/", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> {
|
private fun parseSearchPage(soup: Document): ArrayList<SearchResponse> {
|
||||||
val items = soup.select("ul.thumb > li > a")
|
val items = soup.select("ul.thumb > li > a")
|
||||||
if (items.isEmpty()) return ArrayList()
|
if (items.isEmpty()) return ArrayList()
|
||||||
|
@ -70,13 +66,12 @@ class TenshiProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (getIsMovie(href, true)) {
|
if (getIsMovie(href, true)) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title, href, getSlug(href), this.name, TvType.Movie, img, null
|
title, href, this.name, TvType.Movie, img, null
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
title,
|
title,
|
||||||
href,
|
href,
|
||||||
getSlug(href),
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Anime,
|
TvType.Anime,
|
||||||
img,
|
img,
|
||||||
|
@ -170,9 +165,7 @@ class TenshiProvider : MainAPI() {
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse {
|
override fun load(url: String): LoadResponse {
|
||||||
val url = "$mainUrl/anime/${slug}"
|
|
||||||
|
|
||||||
val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb"))
|
val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb"))
|
||||||
val document = Jsoup.parse(response.text)
|
val document = Jsoup.parse(response.text)
|
||||||
|
|
||||||
|
@ -213,7 +206,7 @@ class TenshiProvider : MainAPI() {
|
||||||
englishTitle,
|
englishTitle,
|
||||||
japaneseTitle,
|
japaneseTitle,
|
||||||
canonicalTitle,
|
canonicalTitle,
|
||||||
"$mainUrl/anime/${slug}",
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
TenshiProvider.getType(type ?: ""),
|
TenshiProvider.getType(type ?: ""),
|
||||||
poster,
|
poster,
|
||||||
|
|
|
@ -25,11 +25,6 @@ class WcoProvider : MainAPI() {
|
||||||
override val hasQuickSearch: Boolean
|
override val hasQuickSearch: Boolean
|
||||||
get() = true
|
get() = true
|
||||||
|
|
||||||
|
|
||||||
private fun getSlug(href: String): String {
|
|
||||||
return href.replace("$mainUrl/anime/", "").replace("/", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fixAnimeLink(url: String): String {
|
private fun fixAnimeLink(url: String): String {
|
||||||
val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex()
|
val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex()
|
||||||
val (aniId) = regex.find(url)!!.destructured
|
val (aniId) = regex.find(url)!!.destructured
|
||||||
|
@ -51,13 +46,12 @@ class WcoProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (getType(type) == TvType.Movie) {
|
if (getType(type) == TvType.Movie) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title, href, getSlug(href), this.name, TvType.Movie, img, year
|
title, href, this.name, TvType.Movie, img, year
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
title,
|
title,
|
||||||
href,
|
href,
|
||||||
getSlug(href),
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Anime,
|
TvType.Anime,
|
||||||
img,
|
img,
|
||||||
|
@ -113,13 +107,12 @@ class WcoProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (getType(type) == TvType.Movie) {
|
if (getType(type) == TvType.Movie) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title, href, getSlug(href), this.name, TvType.Movie, img, year
|
title, href, this.name, TvType.Movie, img, year
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
title,
|
title,
|
||||||
href,
|
href,
|
||||||
getSlug(href),
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Anime,
|
TvType.Anime,
|
||||||
img,
|
img,
|
||||||
|
@ -136,9 +129,7 @@ class WcoProvider : MainAPI() {
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse {
|
override fun load(url: String): LoadResponse {
|
||||||
val url = "$mainUrl/anime/${slug}"
|
|
||||||
|
|
||||||
val response = khttp.get(url, timeout = 120.0)
|
val response = khttp.get(url, timeout = 120.0)
|
||||||
val document = Jsoup.parse(response.text)
|
val document = Jsoup.parse(response.text)
|
||||||
|
|
||||||
|
@ -174,7 +165,7 @@ class WcoProvider : MainAPI() {
|
||||||
canonicalTitle,
|
canonicalTitle,
|
||||||
japaneseTitle,
|
japaneseTitle,
|
||||||
canonicalTitle,
|
canonicalTitle,
|
||||||
"$mainUrl/anime/${slug}",
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
getType(type ?: ""),
|
getType(type ?: ""),
|
||||||
poster,
|
poster,
|
||||||
|
|
|
@ -25,7 +25,7 @@ class HDMProvider : MainAPI() {
|
||||||
val data = i.selectFirst("> div.item")
|
val data = i.selectFirst("> div.item")
|
||||||
val img = data.selectFirst("> img").attr("src")
|
val img = data.selectFirst("> img").attr("src")
|
||||||
val name = data.selectFirst("> div.movie-details").text()
|
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
|
return returnValue
|
||||||
|
@ -54,8 +54,8 @@ class HDMProvider : MainAPI() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse? {
|
override fun load(url: String): LoadResponse? {
|
||||||
val response = khttp.get(slug)
|
val response = khttp.get(url)
|
||||||
val document = Jsoup.parse(response.text)
|
val document = Jsoup.parse(response.text)
|
||||||
val title = document.selectFirst("h2.movieTitle").text()
|
val title = document.selectFirst("h2.movieTitle").text()
|
||||||
val poster = document.selectFirst("div.post-thumbnail > img").attr("src")
|
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
|
val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null
|
||||||
|
|
||||||
return MovieLoadResponse(
|
return MovieLoadResponse(
|
||||||
title, slug, this.name, TvType.Movie,
|
title, url, this.name, TvType.Movie,
|
||||||
"$mainUrl/src/player/?v=$data", poster, year, descript, null
|
"$mainUrl/src/player/?v=$data", poster, year, descript, null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,6 @@ class LookMovieProvider : MainAPI() {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
m.title,
|
m.title,
|
||||||
url,
|
url,
|
||||||
url,//m.slug,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
m.poster ?: m.backdrop,
|
m.poster ?: m.backdrop,
|
||||||
|
@ -97,7 +96,6 @@ class LookMovieProvider : MainAPI() {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
s.title,
|
s.title,
|
||||||
url,
|
url,
|
||||||
url,//s.slug,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
s.poster ?: s.backdrop,
|
s.poster ?: s.backdrop,
|
||||||
|
@ -129,11 +127,11 @@ class LookMovieProvider : MainAPI() {
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (isMovie) {
|
if (isMovie) {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
name, href, href, this.name, TvType.Movie, poster, year
|
name, href, this.name, TvType.Movie, poster, year
|
||||||
)
|
)
|
||||||
} else
|
} else
|
||||||
TvSeriesSearchResponse(
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse? {
|
override fun load(url: String): LoadResponse? {
|
||||||
val response = khttp.get(slug)
|
val response = khttp.get(url)
|
||||||
val document = Jsoup.parse(response.text)
|
val document = Jsoup.parse(response.text)
|
||||||
val isMovie = slug.contains("/movies/")
|
val isMovie = url.contains("/movies/")
|
||||||
|
|
||||||
val watchHeader = document.selectFirst("div.watch-heading")
|
val watchHeader = document.selectFirst("div.watch-heading")
|
||||||
val nameHeader = watchHeader.selectFirst("> h1.bd-hd")
|
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)
|
val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1)
|
||||||
?.replace(" ", "")
|
?.replace(" ", "")
|
||||||
?: return null
|
?: 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 =
|
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"
|
"$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(
|
return MovieLoadResponse(
|
||||||
title,
|
title,
|
||||||
slug,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
localData,
|
localData,
|
||||||
|
@ -280,7 +278,7 @@ class LookMovieProvider : MainAPI() {
|
||||||
|
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
title,
|
||||||
slug,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
ArrayList(episodes),
|
ArrayList(episodes),
|
||||||
|
|
|
@ -50,7 +50,6 @@ class MeloMovieProvider : MainAPI() {
|
||||||
TvSeriesSearchResponse(
|
TvSeriesSearchResponse(
|
||||||
i.title,
|
i.title,
|
||||||
currentUrl,
|
currentUrl,
|
||||||
currentUrl,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
currentPoster,
|
currentPoster,
|
||||||
|
@ -63,7 +62,6 @@ class MeloMovieProvider : MainAPI() {
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
i.title,
|
i.title,
|
||||||
currentUrl,
|
currentUrl,
|
||||||
currentUrl,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
currentUrl,
|
currentUrl,
|
||||||
|
@ -116,8 +114,8 @@ class MeloMovieProvider : MainAPI() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun load(slug: String): LoadResponse? {
|
override fun load(url: String): LoadResponse? {
|
||||||
val response = khttp.get(slug).text
|
val response = khttp.get(url).text
|
||||||
|
|
||||||
//backdrop = imgurl
|
//backdrop = imgurl
|
||||||
fun findUsingRegex(src: String): String? {
|
fun findUsingRegex(src: String): String? {
|
||||||
|
@ -137,7 +135,7 @@ class MeloMovieProvider : MainAPI() {
|
||||||
val serialize = document.selectFirst("table.accordion__list")
|
val serialize = document.selectFirst("table.accordion__list")
|
||||||
return MovieLoadResponse(
|
return MovieLoadResponse(
|
||||||
title,
|
title,
|
||||||
slug,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
serializeData(serialize),
|
serializeData(serialize),
|
||||||
|
@ -164,7 +162,7 @@ class MeloMovieProvider : MainAPI() {
|
||||||
episodes.reverse()
|
episodes.reverse()
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
title,
|
||||||
slug,
|
url,
|
||||||
this.name,
|
this.name,
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
episodes,
|
episodes,
|
||||||
|
|
|
@ -40,7 +40,6 @@ class TrailersToProvider : MainAPI() {
|
||||||
return@mapNotNull if (isMovieType) MovieSearchResponse(
|
return@mapNotNull if (isMovieType) MovieSearchResponse(
|
||||||
name,
|
name,
|
||||||
href,
|
href,
|
||||||
href,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
posterUrl,
|
posterUrl,
|
||||||
|
@ -48,7 +47,6 @@ class TrailersToProvider : MainAPI() {
|
||||||
) else TvSeriesSearchResponse(
|
) else TvSeriesSearchResponse(
|
||||||
name,
|
name,
|
||||||
href,
|
href,
|
||||||
href,
|
|
||||||
this.name,
|
this.name,
|
||||||
TvType.TvSeries,
|
TvType.TvSeries,
|
||||||
posterUrl,
|
posterUrl,
|
||||||
|
@ -84,9 +82,9 @@ class TrailersToProvider : MainAPI() {
|
||||||
|
|
||||||
returnValue.add(
|
returnValue.add(
|
||||||
if (isTvShow) {
|
if (isTvShow) {
|
||||||
TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null)
|
TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null)
|
||||||
} else {
|
} 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(
|
returnValue.add(
|
||||||
if (isTvShow) {
|
if (isTvShow) {
|
||||||
TvSeriesSearchResponse(name, href, href, this.name, TvType.TvSeries, poster, year, null)
|
TvSeriesSearchResponse(name, href, this.name, TvType.TvSeries, poster, year, null)
|
||||||
} else {
|
} 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 ErrorLoadingException(message: String) : Exception(message)
|
||||||
|
|
||||||
class APIRepository(val api: MainAPI) {
|
class APIRepository(val api: MainAPI) {
|
||||||
val name : String get() = api.name
|
val name: String get() = api.name
|
||||||
val mainUrl : String get() = api.mainUrl
|
val mainUrl: String get() = api.mainUrl
|
||||||
|
|
||||||
suspend fun load(url: String): Resource<LoadResponse> {
|
suspend fun load(url: String): Resource<LoadResponse> {
|
||||||
return safeApiCall {
|
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() {
|
class ResultFragment : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance(url: String, slug: String, apiName: String, startAction: Int = 0) =
|
fun newInstance(url: String, apiName: String, startAction: Int = 0) =
|
||||||
ResultFragment().apply {
|
ResultFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putString("url", url)
|
putString("url", url)
|
||||||
putString("slug", slug)
|
|
||||||
putString("apiName", apiName)
|
putString("apiName", apiName)
|
||||||
putInt("startAction", startAction)
|
putInt("startAction", startAction)
|
||||||
}
|
}
|
||||||
|
@ -257,7 +256,6 @@ class ResultFragment : Fragment() {
|
||||||
// activity?.fixPaddingStatusbar(result_toolbar)
|
// activity?.fixPaddingStatusbar(result_toolbar)
|
||||||
|
|
||||||
url = arguments?.getString("url")
|
url = arguments?.getString("url")
|
||||||
val slug = arguments?.getString("slug")
|
|
||||||
val apiName = arguments?.getString("apiName") ?: return
|
val apiName = arguments?.getString("apiName") ?: return
|
||||||
startAction = arguments?.getInt("startAction") ?: START_ACTION_NORMAL
|
startAction = arguments?.getInt("startAction") ?: START_ACTION_NORMAL
|
||||||
|
|
||||||
|
@ -431,7 +429,6 @@ class ResultFragment : Fragment() {
|
||||||
VideoDownloadHelper.DownloadHeaderCached(
|
VideoDownloadHelper.DownloadHeaderCached(
|
||||||
apiName,
|
apiName,
|
||||||
url ?: return@let,
|
url ?: return@let,
|
||||||
slug ?: return@let,
|
|
||||||
currentType ?: return@let,
|
currentType ?: return@let,
|
||||||
currentHeaderName ?: return@let,
|
currentHeaderName ?: return@let,
|
||||||
currentPoster ?: 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 {
|
result_reload_connectionerror.setOnClickListener {
|
||||||
viewModel.load(requireContext(), slug, apiName)
|
viewModel.load(requireContext(), tempUrl, apiName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url != null) {
|
result_reload_connection_open_in_browser.setOnClickListener {
|
||||||
result_reload_connection_open_in_browser.setOnClickListener {
|
val i = Intent(ACTION_VIEW)
|
||||||
val i = Intent(ACTION_VIEW)
|
i.data = Uri.parse(tempUrl)
|
||||||
i.data = Uri.parse(url)
|
startActivity(i)
|
||||||
startActivity(i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.resultResponse.value == null)
|
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.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
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.getResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.getResultWatchState
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos
|
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.setResultSeason
|
||||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
@ -21,7 +23,7 @@ const val EPISODE_RANGE_SIZE = 50
|
||||||
const val EPISODE_RANGE_OVERLOAD = 60
|
const val EPISODE_RANGE_OVERLOAD = 60
|
||||||
|
|
||||||
class ResultViewModel : ViewModel() {
|
class ResultViewModel : ViewModel() {
|
||||||
var repo : APIRepository? = null
|
var repo: APIRepository? = null
|
||||||
|
|
||||||
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
private val _resultResponse: MutableLiveData<Resource<Any?>> = MutableLiveData()
|
||||||
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
|
private val _episodes: MutableLiveData<List<ResultEpisode>> = MutableLiveData()
|
||||||
|
@ -51,6 +53,21 @@ class ResultViewModel : ViewModel() {
|
||||||
val currentId = id.value ?: return
|
val currentId = id.value ?: return
|
||||||
_watchStatus.postValue(status)
|
_watchStatus.postValue(status)
|
||||||
context.setResultWatchState(currentId, status.internalId)
|
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) {
|
private fun loadWatchStatus(context: Context, localId: Int? = null) {
|
||||||
|
@ -154,80 +171,78 @@ class ResultViewModel : ViewModel() {
|
||||||
when (data) {
|
when (data) {
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
val d = data.value
|
val d = data.value
|
||||||
if (d is LoadResponse) {
|
page.postValue(d)
|
||||||
page.postValue(d)
|
val mainId = d.getId()
|
||||||
val mainId = d.getId()
|
id.postValue(mainId)
|
||||||
id.postValue(mainId)
|
loadWatchStatus(context, mainId)
|
||||||
loadWatchStatus(context, mainId)
|
|
||||||
|
|
||||||
when (d) {
|
when (d) {
|
||||||
is AnimeLoadResponse -> {
|
is AnimeLoadResponse -> {
|
||||||
val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0
|
val isDub = d.dubEpisodes != null && d.dubEpisodes.size > 0
|
||||||
dubStatus.postValue(if (isDub) DubStatus.Dubbed else DubStatus.Subbed)
|
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) {
|
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 -> {
|
|
||||||
val episodes = ArrayList<ResultEpisode>()
|
val episodes = ArrayList<ResultEpisode>()
|
||||||
for ((index, i) in d.episodes.withIndex()) {
|
for ((index, i) in dataList.withIndex()) {
|
||||||
episodes.add(
|
episodes.add(
|
||||||
context.buildResultEpisode(
|
context.buildResultEpisode(
|
||||||
i.name,
|
i.name,
|
||||||
//?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
|
|
||||||
i.posterUrl,
|
i.posterUrl,
|
||||||
i.episode ?: (index + 1),
|
index + 1, //TODO MAKE ABLE TO NOT HAVE SOME EPISODE
|
||||||
i.season,
|
null, // TODO FIX SEASON
|
||||||
i.data,
|
i.url,
|
||||||
apiName,
|
apiName,
|
||||||
(mainId + index + 1).hashCode(),
|
(mainId + index + 1),
|
||||||
index,
|
index,
|
||||||
i.rating,
|
i.rating,
|
||||||
i.descript
|
i.descript,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
updateEpisodes(context, mainId, episodes, -1)
|
updateEpisodes(context, mainId, episodes, -1)
|
||||||
}
|
}
|
||||||
is MovieLoadResponse -> {
|
}
|
||||||
updateEpisodes(
|
|
||||||
context, mainId, arrayListOf(
|
is TvSeriesLoadResponse -> {
|
||||||
context.buildResultEpisode(
|
val episodes = ArrayList<ResultEpisode>()
|
||||||
d.name,
|
for ((index, i) in d.episodes.withIndex()) {
|
||||||
null,
|
episodes.add(
|
||||||
0,
|
context.buildResultEpisode(
|
||||||
null,
|
i.name,
|
||||||
d.dataUrl,
|
//?: (if (i.season != null && i.episode != null) "S${i.season}:E${i.episode}" else null)), // TODO ADD NAMES
|
||||||
d.apiName,
|
i.posterUrl,
|
||||||
(mainId), // HAS SAME ID
|
i.episode ?: (index + 1),
|
||||||
0,
|
i.season,
|
||||||
null,
|
i.data,
|
||||||
null,
|
apiName,
|
||||||
)
|
(mainId + index + 1).hashCode(),
|
||||||
), -1
|
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)
|
val localData = loadEpisode(id, data, isCasting)
|
||||||
callback.invoke(localData)
|
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
|
search_loading_bar.alpha = 0f
|
||||||
}
|
}
|
||||||
is Resource.Failure -> {
|
is Resource.Failure -> {
|
||||||
Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
// Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||||
searchExitIcon.alpha = 1f
|
searchExitIcon.alpha = 1f
|
||||||
search_loading_bar.alpha = 0f
|
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 {
|
this.runOnUiThread {
|
||||||
viewModelStore.clear()
|
viewModelStore.clear()
|
||||||
this.supportFragmentManager.beginTransaction()
|
this.supportFragmentManager.beginTransaction()
|
||||||
.setCustomAnimations(R.anim.enter_anim, R.anim.exit_anim, R.anim.pop_enter, R.anim.pop_exit)
|
.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()
|
.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity?.loadSearchResult(card: SearchResponse, startAction: Int = 0) {
|
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?) {
|
fun Activity.requestLocalAudioFocus(focusRequest: AudioFocusRequest?) {
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.lagradost.cloudstream3.SearchResponse
|
||||||
|
import com.lagradost.cloudstream3.TvType
|
||||||
import com.lagradost.cloudstream3.ui.WatchType
|
import com.lagradost.cloudstream3.ui.WatchType
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||||
|
|
||||||
const val VIDEO_POS_DUR = "video_pos_dur"
|
const val VIDEO_POS_DUR = "video_pos_dur"
|
||||||
const val RESULT_WATCH_STATE = "result_watch_state"
|
const val RESULT_WATCH_STATE = "result_watch_state"
|
||||||
|
const val RESULT_WATCH_STATE_DATA = "result_watch_state_data"
|
||||||
const val RESULT_SEASON = "result_season"
|
const val RESULT_SEASON = "result_season"
|
||||||
|
|
||||||
|
|
||||||
object DataStoreHelper {
|
object DataStoreHelper {
|
||||||
data class PosDur(val position: Long, val duration: Long)
|
data class PosDur(val position: Long, val duration: Long)
|
||||||
|
|
||||||
fun PosDur.fixVisual(): PosDur {
|
fun PosDur.fixVisual(): PosDur {
|
||||||
if (duration <= 0) return PosDur(0, duration)
|
if (duration <= 0) return PosDur(0, duration)
|
||||||
val percentage = position * 100 / duration
|
val percentage = position * 100 / duration
|
||||||
|
@ -21,8 +25,28 @@ object DataStoreHelper {
|
||||||
return this
|
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
|
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) {
|
fun Context.setViewPos(id: Int?, pos: Long, dur: Long) {
|
||||||
if (id == null) return
|
if (id == null) return
|
||||||
setKey("$currentAccount/$VIDEO_POS_DUR", id.toString(), PosDur(pos, dur))
|
setKey("$currentAccount/$VIDEO_POS_DUR", id.toString(), PosDur(pos, dur))
|
||||||
|
@ -44,7 +68,8 @@ object DataStoreHelper {
|
||||||
fun Context.getResultSeason(id: Int): Int {
|
fun Context.getResultSeason(id: Int): Int {
|
||||||
return getKey("$currentAccount/$RESULT_SEASON", id.toString(), -1)!!
|
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)
|
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.extractors.*
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.extractors.*
|
|
||||||
|
|
||||||
data class ExtractorLink(
|
data class ExtractorLink(
|
||||||
val source: String,
|
val source: String,
|
||||||
|
|
|
@ -17,7 +17,6 @@ object VideoDownloadHelper {
|
||||||
data class DownloadHeaderCached(
|
data class DownloadHeaderCached(
|
||||||
val apiName: String,
|
val apiName: String,
|
||||||
val url: String,
|
val url: String,
|
||||||
val slug : String,
|
|
||||||
val type : TvType,
|
val type : TvType,
|
||||||
val name: String,
|
val name: String,
|
||||||
val poster: 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:id="@+id/home_loaded"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -202,6 +203,57 @@
|
||||||
</ImageView>
|
</ImageView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</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
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/home_master_recycler"
|
android:id="@+id/home_master_recycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -210,5 +262,4 @@
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -108,6 +108,7 @@
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:visibility="gone"
|
||||||
android:alpha="0"
|
android:alpha="0"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/result_poster_blur_holder"
|
android:id="@+id/result_poster_blur_holder"
|
||||||
|
@ -120,10 +121,13 @@
|
||||||
tools:src="@drawable/example_poster"
|
tools:src="@drawable/example_poster"
|
||||||
android:background="@color/darkBackground"
|
android:background="@color/darkBackground"
|
||||||
android:id="@+id/result_poster_blur"
|
android:id="@+id/result_poster_blur"
|
||||||
android:contentDescription=""/>
|
android:contentDescription="@string/background_blur"/>
|
||||||
<ImageView android:src="@drawable/background_shadow" android:layout_gravity="bottom"
|
<ImageView
|
||||||
android:layout_width="match_parent" android:layout_height="30dp">
|
android:src="@drawable/background_shadow"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:contentDescription="@string/background_shadow">
|
||||||
</ImageView>
|
</ImageView>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
@ -163,13 +167,13 @@
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginLeft="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_marginRight="50dp"
|
android:layout_marginEnd="50dp"
|
||||||
tools:text="The Perfect Run The Perfect Run The Perfect Run"
|
tools:text="The Perfect Run The Perfect Run The Perfect Run"
|
||||||
android:id="@+id/result_title"
|
android:id="@+id/result_title"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
@ -201,7 +205,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="50dp">
|
android:layout_height="50dp">
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
app:cornerRadius="4dp"
|
app:cornerRadius="4dp"
|
||||||
android:id="@+id/result_bookmark_button"
|
android:id="@+id/result_bookmark_button"
|
||||||
|
|
|
@ -4,7 +4,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"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
android:id="@+id/home_child_recyclerview"
|
android:id="@+id/home_child_recyclerview"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:listitem="@layout/home_result_grid"
|
tools:listitem="@layout/home_result_grid"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -61,4 +61,7 @@
|
||||||
<string name="home_info">Info</string>
|
<string name="home_info">Info</string>
|
||||||
<string name="home_next_random">Next Random</string>
|
<string name="home_next_random">Next Random</string>
|
||||||
<string name="home_change_provider">Change Provider</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>
|
</resources>
|
Loading…
Reference in a new issue