forked from recloudstream/cloudstream
		
	fixed sync stuff and tv stuff
This commit is contained in:
		
							parent
							
								
									10c945f497
								
							
						
					
					
						commit
						7cbdc1fc6c
					
				
					 24 changed files with 209 additions and 160 deletions
				
			
		|  | @ -13,6 +13,8 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||||
| import com.lagradost.cloudstream3.animeproviders.* | import com.lagradost.cloudstream3.animeproviders.* | ||||||
| import com.lagradost.cloudstream3.metaproviders.CrossTmdbProvider | import com.lagradost.cloudstream3.metaproviders.CrossTmdbProvider | ||||||
| import com.lagradost.cloudstream3.movieproviders.* | import com.lagradost.cloudstream3.movieproviders.* | ||||||
|  | import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi | ||||||
|  | import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.malApi | ||||||
| import com.lagradost.cloudstream3.ui.player.SubtitleData | import com.lagradost.cloudstream3.ui.player.SubtitleData | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import okhttp3.Interceptor | import okhttp3.Interceptor | ||||||
|  | @ -119,10 +121,10 @@ object APIHolder { | ||||||
|         return null |         return null | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun getApiFromUrlNull(url : String?) : MainAPI? { |     fun getApiFromUrlNull(url: String?): MainAPI? { | ||||||
|         if (url == null) return null |         if (url == null) return null | ||||||
|         for (api in allProviders) { |         for (api in allProviders) { | ||||||
|             if(url.startsWith(api.mainUrl)) |             if (url.startsWith(api.mainUrl)) | ||||||
|                 return api |                 return api | ||||||
|         } |         } | ||||||
|         return null |         return null | ||||||
|  | @ -397,7 +399,7 @@ abstract class MainAPI { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** An okhttp interceptor for used in OkHttpDataSource */ |     /** An okhttp interceptor for used in OkHttpDataSource */ | ||||||
|     open fun getVideoInterceptor(extractorLink: ExtractorLink) : Interceptor? { |     open fun getVideoInterceptor(extractorLink: ExtractorLink): Interceptor? { | ||||||
|         return null |         return null | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -571,10 +573,10 @@ enum class SearchQuality { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**Add anything to here if you find a site that uses some specific naming convention*/ | /**Add anything to here if you find a site that uses some specific naming convention*/ | ||||||
| fun getQualityFromString(string: String?) : SearchQuality? { | fun getQualityFromString(string: String?): SearchQuality? { | ||||||
|     val check = (string ?: return null).trim().lowercase().replace(" ","") |     val check = (string ?: return null).trim().lowercase().replace(" ", "") | ||||||
| 
 | 
 | ||||||
|     return when(check) { |     return when (check) { | ||||||
|         "cam" -> SearchQuality.Cam |         "cam" -> SearchQuality.Cam | ||||||
|         "camrip" -> SearchQuality.CamRip |         "camrip" -> SearchQuality.CamRip | ||||||
|         "hdcam" -> SearchQuality.HdCam |         "hdcam" -> SearchQuality.HdCam | ||||||
|  | @ -614,7 +616,7 @@ interface SearchResponse { | ||||||
|     var type: TvType? |     var type: TvType? | ||||||
|     var posterUrl: String? |     var posterUrl: String? | ||||||
|     var id: Int? |     var id: Int? | ||||||
|     var quality : SearchQuality? |     var quality: SearchQuality? | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum class ActorRole { | enum class ActorRole { | ||||||
|  | @ -703,8 +705,12 @@ interface LoadResponse { | ||||||
|     var recommendations: List<SearchResponse>? |     var recommendations: List<SearchResponse>? | ||||||
|     var actors: List<ActorData>? |     var actors: List<ActorData>? | ||||||
|     var comingSoon: Boolean |     var comingSoon: Boolean | ||||||
|  |     var syncData: MutableMap<String, String> | ||||||
| 
 | 
 | ||||||
|     companion object { |     companion object { | ||||||
|  |         val malIdPrefix = malApi.idPrefix | ||||||
|  |         val aniListIdPrefix = aniListApi.idPrefix | ||||||
|  | 
 | ||||||
|         @JvmName("addActorNames") |         @JvmName("addActorNames") | ||||||
|         fun LoadResponse.addActors(actors: List<String>?) { |         fun LoadResponse.addActors(actors: List<String>?) { | ||||||
|             this.actors = actors?.map { ActorData(Actor(it)) } |             this.actors = actors?.map { ActorData(Actor(it)) } | ||||||
|  | @ -725,6 +731,30 @@ interface LoadResponse { | ||||||
|             this.actors = actors?.map { actor -> ActorData(actor) } |             this.actors = actors?.map { actor -> ActorData(actor) } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         fun LoadResponse.addMalId(id: Int?) { | ||||||
|  |             this.syncData[malIdPrefix] = (id ?: return).toString() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun LoadResponse.addAniListId(id: Int?) { | ||||||
|  |             this.syncData[aniListIdPrefix] = (id ?: return).toString() | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun LoadResponse.addImdbUrl(url : String?) { | ||||||
|  |             addImdbId(imdbUrlToIdNullable(url)) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun LoadResponse.addImdbId(id: String?) { | ||||||
|  |             // TODO add imdb sync | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun LoadResponse.addTrackId(id: String?) { | ||||||
|  |             // TODO add trackt sync | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun LoadResponse.addkitsuId(id: String?) { | ||||||
|  |             // TODO add kitsu sync | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         fun LoadResponse.setDuration(input: String?) { |         fun LoadResponse.setDuration(input: String?) { | ||||||
|             val cleanInput = input?.trim()?.replace(" ", "") ?: return |             val cleanInput = input?.trim()?.replace(" ", "") ?: return | ||||||
|             Regex("([0-9]*)h.*?([0-9]*)m").find(cleanInput)?.groupValues?.let { values -> |             Regex("([0-9]*)h.*?([0-9]*)m").find(cleanInput)?.groupValues?.let { values -> | ||||||
|  | @ -789,6 +819,7 @@ data class TorrentLoadResponse( | ||||||
|     override var recommendations: List<SearchResponse>? = null, |     override var recommendations: List<SearchResponse>? = null, | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|  |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| data class AnimeLoadResponse( | data class AnimeLoadResponse( | ||||||
|  | @ -802,21 +833,20 @@ data class AnimeLoadResponse( | ||||||
|     override var posterUrl: String? = null, |     override var posterUrl: String? = null, | ||||||
|     override var year: Int? = null, |     override var year: Int? = null, | ||||||
| 
 | 
 | ||||||
|     var episodes: HashMap<DubStatus, List<AnimeEpisode>> = hashMapOf(), |     var episodes: MutableMap<DubStatus, List<AnimeEpisode>> = mutableMapOf(), | ||||||
|     var showStatus: ShowStatus? = null, |     var showStatus: ShowStatus? = null, | ||||||
| 
 | 
 | ||||||
|     override var plot: String? = null, |     override var plot: String? = null, | ||||||
|     override var tags: List<String>? = null, |     override var tags: List<String>? = null, | ||||||
|     var synonyms: List<String>? = null, |     var synonyms: List<String>? = null, | ||||||
| 
 | 
 | ||||||
|     var malId: Int? = null, |  | ||||||
|     var anilistId: Int? = null, |  | ||||||
|     override var rating: Int? = null, |     override var rating: Int? = null, | ||||||
|     override var duration: Int? = null, |     override var duration: Int? = null, | ||||||
|     override var trailerUrl: String? = null, |     override var trailerUrl: String? = null, | ||||||
|     override var recommendations: List<SearchResponse>? = null, |     override var recommendations: List<SearchResponse>? = null, | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|  |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<AnimeEpisode>?) { | fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<AnimeEpisode>?) { | ||||||
|  | @ -828,15 +858,15 @@ fun MainAPI.newAnimeLoadResponse( | ||||||
|     name: String, |     name: String, | ||||||
|     url: String, |     url: String, | ||||||
|     type: TvType, |     type: TvType, | ||||||
|     comingSoonIfNone : Boolean, |     comingSoonIfNone: Boolean, | ||||||
|     initializer: AnimeLoadResponse.() -> Unit = { }, |     initializer: AnimeLoadResponse.() -> Unit = { }, | ||||||
| ): AnimeLoadResponse { | ): AnimeLoadResponse { | ||||||
|     val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) |     val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) | ||||||
|     builder.initializer() |     builder.initializer() | ||||||
|     if(comingSoonIfNone) { |     if (comingSoonIfNone) { | ||||||
|         builder.comingSoon = true |         builder.comingSoon = true | ||||||
|         for (key in builder.episodes.keys) |         for (key in builder.episodes.keys) | ||||||
|             if(!builder.episodes[key].isNullOrEmpty()) { |             if (!builder.episodes[key].isNullOrEmpty()) { | ||||||
|                 builder.comingSoon = false |                 builder.comingSoon = false | ||||||
|                 break |                 break | ||||||
|             } |             } | ||||||
|  | @ -864,7 +894,6 @@ data class MovieLoadResponse( | ||||||
|     override var year: Int? = null, |     override var year: Int? = null, | ||||||
|     override var plot: String? = null, |     override var plot: String? = null, | ||||||
| 
 | 
 | ||||||
|     var imdbId: String? = null, |  | ||||||
|     override var rating: Int? = null, |     override var rating: Int? = null, | ||||||
|     override var tags: List<String>? = null, |     override var tags: List<String>? = null, | ||||||
|     override var duration: Int? = null, |     override var duration: Int? = null, | ||||||
|  | @ -872,6 +901,7 @@ data class MovieLoadResponse( | ||||||
|     override var recommendations: List<SearchResponse>? = null, |     override var recommendations: List<SearchResponse>? = null, | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|  |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun MainAPI.newMovieLoadResponse( | fun MainAPI.newMovieLoadResponse( | ||||||
|  | @ -916,7 +946,6 @@ data class TvSeriesLoadResponse( | ||||||
|     override var plot: String? = null, |     override var plot: String? = null, | ||||||
| 
 | 
 | ||||||
|     var showStatus: ShowStatus? = null, |     var showStatus: ShowStatus? = null, | ||||||
|     var imdbId: String? = null, |  | ||||||
|     override var rating: Int? = null, |     override var rating: Int? = null, | ||||||
|     override var tags: List<String>? = null, |     override var tags: List<String>? = null, | ||||||
|     override var duration: Int? = null, |     override var duration: Int? = null, | ||||||
|  | @ -924,6 +953,7 @@ data class TvSeriesLoadResponse( | ||||||
|     override var recommendations: List<SearchResponse>? = null, |     override var recommendations: List<SearchResponse>? = null, | ||||||
|     override var actors: List<ActorData>? = null, |     override var actors: List<ActorData>? = null, | ||||||
|     override var comingSoon: Boolean = false, |     override var comingSoon: Boolean = false, | ||||||
|  |     override var syncData: MutableMap<String, String> = mutableMapOf(), | ||||||
| ) : LoadResponse | ) : LoadResponse | ||||||
| 
 | 
 | ||||||
| fun MainAPI.newTvSeriesLoadResponse( | fun MainAPI.newTvSeriesLoadResponse( | ||||||
|  | @ -954,5 +984,5 @@ fun fetchUrls(text: String?): List<String> { | ||||||
|     return linkRegex.findAll(text).map { it.value.trim().removeSurrounding("\"") }.toList() |     return linkRegex.findAll(text).map { it.value.trim().removeSurrounding("\"") }.toList() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fun String?.toRatingInt() : Int? = | fun String?.toRatingInt(): Int? = | ||||||
|     this?.trim()?.toDoubleOrNull()?.absoluteValue?.times(1000f)?.toInt() |     this?.trim()?.toDoubleOrNull()?.absoluteValue?.times(1000f)?.toInt() | ||||||
|  |  | ||||||
|  | @ -275,21 +275,26 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | ||||||
|                     if (str.contains("/${api.redirectUrl}")) { |                     if (str.contains("/${api.redirectUrl}")) { | ||||||
|                         ioSafe { |                         ioSafe { | ||||||
|                             Log.i(TAG, "handleAppIntent $str") |                             Log.i(TAG, "handleAppIntent $str") | ||||||
|                             if (api.handleRedirect(str)) { |                             val isSuccessful = api.handleRedirect(str) | ||||||
|  | 
 | ||||||
|  |                             if (isSuccessful) { | ||||||
|                                 Log.i(TAG, "authenticated ${api.name}") |                                 Log.i(TAG, "authenticated ${api.name}") | ||||||
|  |                             } else { | ||||||
|  |                                 Log.i(TAG, "failed to authenticate ${api.name}") | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|                             this.runOnUiThread { |                             this.runOnUiThread { | ||||||
|                                 try { |                                 try { | ||||||
|                                     showToast( |                                     showToast( | ||||||
|                                         this, |                                         this, | ||||||
|                                             getString(R.string.authenticated_user).format(api.name) |                                         getString(if (isSuccessful) R.string.authenticated_user else R.string.authenticated_user_fail).format( | ||||||
|  |                                             api.name | ||||||
|  |                                         ) | ||||||
|                                     ) |                                     ) | ||||||
|                                 } catch (e: Exception) { |                                 } catch (e: Exception) { | ||||||
|                                     logError(e) // format might fail |                                     logError(e) // format might fail | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|                             } else { |  | ||||||
|                                 Log.i(TAG, "failed to authenticate ${api.name}") |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ package com.lagradost.cloudstream3.animeproviders | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.fasterxml.jackson.module.kotlin.readValue | import com.fasterxml.jackson.module.kotlin.readValue | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId | ||||||
| import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall | import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall | ||||||
| import com.lagradost.cloudstream3.network.AppResponse | import com.lagradost.cloudstream3.network.AppResponse | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | @ -305,8 +307,8 @@ class AnimePaheProvider : MainAPI() { | ||||||
|                     null |                     null | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 this.malId = malId |                 addMalId(malId) | ||||||
|                 this.anilistId = anilistId |                 addAniListId(anilistId) | ||||||
|                 this.trailerUrl = trailer |                 this.trailerUrl = trailer | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| package com.lagradost.cloudstream3.animeproviders | package com.lagradost.cloudstream3.animeproviders | ||||||
| 
 | 
 | ||||||
| import java.util.* |  | ||||||
| import org.json.JSONObject |  | ||||||
| import org.jsoup.nodes.Element |  | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
| import com.lagradost.cloudstream3.utils.Qualities | import com.lagradost.cloudstream3.utils.Qualities | ||||||
|  | import org.json.JSONObject | ||||||
|  | import org.jsoup.nodes.Element | ||||||
|  | import java.util.* | ||||||
| 
 | 
 | ||||||
| class AnimeWorldProvider : MainAPI() { | class AnimeWorldProvider : MainAPI() { | ||||||
|     override var mainUrl = "https://www.animeworld.tv" |     override var mainUrl = "https://www.animeworld.tv" | ||||||
|  | @ -170,8 +172,8 @@ class AnimeWorldProvider : MainAPI() { | ||||||
|             showStatus = status |             showStatus = status | ||||||
|             plot = description |             plot = description | ||||||
|             tags = genres |             tags = genres | ||||||
|             this.malId = malId |             addMalId(malId) | ||||||
|             this.anilistId = anlId |             addAniListId(anlId) | ||||||
|             this.rating = rating |             this.rating = rating | ||||||
|             this.duration = duration |             this.duration = duration | ||||||
|             this.trailerUrl = trailerUrl |             this.trailerUrl = trailerUrl | ||||||
|  |  | ||||||
|  | @ -4,6 +4,8 @@ import android.util.Log | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.fasterxml.jackson.module.kotlin.readValue | import com.fasterxml.jackson.module.kotlin.readValue | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId | ||||||
| import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream | import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream | ||||||
| import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob | import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob | ||||||
| import com.lagradost.cloudstream3.network.Requests.Companion.await | import com.lagradost.cloudstream3.network.Requests.Companion.await | ||||||
|  | @ -291,8 +293,8 @@ class ZoroProvider : MainAPI() { | ||||||
|             this.tags = tags |             this.tags = tags | ||||||
|             this.recommendations = recommendations |             this.recommendations = recommendations | ||||||
|             this.actors = actors |             this.actors = actors | ||||||
|             this.malId = syncData?.malId?.toIntOrNull() |             addMalId(syncData?.malId?.toIntOrNull()) | ||||||
|             this.anilistId = syncData?.aniListId?.toIntOrNull() |             addAniListId(syncData?.aniListId?.toIntOrNull()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package com.lagradost.cloudstream3.metaproviders | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.LoadResponse.Companion.addActors | import com.lagradost.cloudstream3.LoadResponse.Companion.addActors | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.toJson | import com.lagradost.cloudstream3.utils.AppUtils.toJson | ||||||
| import com.uwetrottmann.tmdb2.Tmdb | import com.uwetrottmann.tmdb2.Tmdb | ||||||
| import com.uwetrottmann.tmdb2.entities.* | import com.uwetrottmann.tmdb2.entities.* | ||||||
|  | @ -135,7 +136,8 @@ open class TmdbProvider : MainAPI() { | ||||||
|                 }.get(Calendar.YEAR) |                 }.get(Calendar.YEAR) | ||||||
|             } |             } | ||||||
|             plot = overview |             plot = overview | ||||||
|             imdbId = external_ids?.imdb_id |             addImdbId(external_ids?.imdb_id) | ||||||
|  | 
 | ||||||
|             tags = genres?.mapNotNull { it.name } |             tags = genres?.mapNotNull { it.name } | ||||||
|             duration = episode_run_time?.average()?.toInt() |             duration = episode_run_time?.average()?.toInt() | ||||||
|             rating = this@toLoadResponse.rating |             rating = this@toLoadResponse.rating | ||||||
|  | @ -163,7 +165,7 @@ open class TmdbProvider : MainAPI() { | ||||||
|                 }.get(Calendar.YEAR) |                 }.get(Calendar.YEAR) | ||||||
|             } |             } | ||||||
|             plot = overview |             plot = overview | ||||||
|             imdbId = external_ids?.imdb_id |             addImdbId(external_ids?.imdb_id) | ||||||
|             tags = genres?.mapNotNull { it.name } |             tags = genres?.mapNotNull { it.name } | ||||||
|             duration = runtime |             duration = runtime | ||||||
|             rating = this@toLoadResponse.rating |             rating = this@toLoadResponse.rating | ||||||
|  | @ -251,7 +253,8 @@ open class TmdbProvider : MainAPI() { | ||||||
|         val found = idRegex.find(url) |         val found = idRegex.find(url) | ||||||
| 
 | 
 | ||||||
|         val isTvSeries = found?.groupValues?.getOrNull(1).equals("tv", ignoreCase = true) |         val isTvSeries = found?.groupValues?.getOrNull(1).equals("tv", ignoreCase = true) | ||||||
|         val id = found?.groupValues?.getOrNull(2)?.toIntOrNull() ?: throw ErrorLoadingException("No id found") |         val id = found?.groupValues?.getOrNull(2)?.toIntOrNull() | ||||||
|  |             ?: throw ErrorLoadingException("No id found") | ||||||
| 
 | 
 | ||||||
|         return if (useMetaLoadResponse) { |         return if (useMetaLoadResponse) { | ||||||
|             return if (isTvSeries) { |             return if (isTvSeries) { | ||||||
|  |  | ||||||
|  | @ -167,7 +167,6 @@ class AllMoviesForYouProvider : MainAPI() { | ||||||
|                 year?.toIntOrNull(), |                 year?.toIntOrNull(), | ||||||
|                 descipt, |                 descipt, | ||||||
|                 null, |                 null, | ||||||
|                 null, |  | ||||||
|                 rating |                 rating | ||||||
|             ) |             ) | ||||||
|         } else { |         } else { | ||||||
|  |  | ||||||
|  | @ -107,7 +107,6 @@ class AsiaFlixProvider : MainAPI() { | ||||||
|             synopsis, |             synopsis, | ||||||
|             getStatus(tvStatus ?: ""), |             getStatus(tvStatus ?: ""), | ||||||
|             null, |             null, | ||||||
|             null, |  | ||||||
|             genre?.split(",")?.map { it.trim() } |             genre?.split(",")?.map { it.trim() } | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -286,7 +286,6 @@ open class BflixProvider() : MainAPI() { | ||||||
|                     year?.toIntOrNull(), |                     year?.toIntOrNull(), | ||||||
|                     description, |                     description, | ||||||
|                     null, |                     null, | ||||||
|                     null, |  | ||||||
|                     rating, |                     rating, | ||||||
|                     tags, |                     tags, | ||||||
|                     recommendations = recommendations, |                     recommendations = recommendations, | ||||||
|  | @ -303,7 +302,6 @@ open class BflixProvider() : MainAPI() { | ||||||
|                     poster, |                     poster, | ||||||
|                     year?.toIntOrNull(), |                     year?.toIntOrNull(), | ||||||
|                     description, |                     description, | ||||||
|                     null, |  | ||||||
|                     rating, |                     rating, | ||||||
|                     tags, |                     tags, | ||||||
|                     recommendations = recommendations, |                     recommendations = recommendations, | ||||||
|  |  | ||||||
|  | @ -182,7 +182,6 @@ class IHaveNoTvProvider : MainAPI() { | ||||||
|                 )?.destructured?.component1()?.toIntOrNull(), |                 )?.destructured?.component1()?.toIntOrNull(), | ||||||
|                 description, |                 description, | ||||||
|                 null, |                 null, | ||||||
|                 null, |  | ||||||
|                 soup.selectFirst(".videoDetails").select("a[href*=\"/category/\"]") |                 soup.selectFirst(".videoDetails").select("a[href*=\"/category/\"]") | ||||||
|                     .map { it.text().trim() } |                     .map { it.text().trim() } | ||||||
|             )) |             )) | ||||||
|  | @ -204,7 +203,6 @@ class IHaveNoTvProvider : MainAPI() { | ||||||
|             description, |             description, | ||||||
|             null, |             null, | ||||||
|             null, |             null, | ||||||
|             null, |  | ||||||
|             categories.toList() |             categories.toList() | ||||||
|         ) else (episodes?.first() as MovieLoadResponse) |         ) else (episodes?.first() as MovieLoadResponse) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -235,7 +235,6 @@ class LookMovieProvider : MainAPI() { | ||||||
|                 poster, |                 poster, | ||||||
|                 year, |                 year, | ||||||
|                 descript, |                 descript, | ||||||
|                 null, |  | ||||||
|                 rating |                 rating | ||||||
|             ) |             ) | ||||||
|         } else { |         } else { | ||||||
|  | @ -292,7 +291,6 @@ class LookMovieProvider : MainAPI() { | ||||||
|                 year, |                 year, | ||||||
|                 descript, |                 descript, | ||||||
|                 null, |                 null, | ||||||
|                 null, |  | ||||||
|                 rating |                 rating | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package com.lagradost.cloudstream3.movieproviders | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.fasterxml.jackson.module.kotlin.readValue | import com.fasterxml.jackson.module.kotlin.readValue | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbUrl | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.parseJson | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.toJson | import com.lagradost.cloudstream3.utils.AppUtils.toJson | ||||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | @ -144,17 +145,17 @@ class MeloMovieProvider : MainAPI() { | ||||||
|         if (type == 1) { // MOVIE |         if (type == 1) { // MOVIE | ||||||
|             val serialize = document.selectFirst("table.accordion__list") |             val serialize = document.selectFirst("table.accordion__list") | ||||||
|                 ?: throw ErrorLoadingException("No links found") |                 ?: throw ErrorLoadingException("No links found") | ||||||
|             return MovieLoadResponse( |             return newMovieLoadResponse( | ||||||
|                 title, |                 title, | ||||||
|                 url, |                 url, | ||||||
|                 this.name, |  | ||||||
|                 TvType.Movie, |                 TvType.Movie, | ||||||
|                 serializeData(serialize), |                 serializeData(serialize) | ||||||
|                 poster, |             ) { | ||||||
|                 year, |                 this.posterUrl = poster | ||||||
|                 plot, |                 this.year = year | ||||||
|                 imdbUrlToIdNullable(imdbUrl) |                 this.plot = plot | ||||||
|             ) |                 addImdbUrl(imdbUrl) | ||||||
|  |             } | ||||||
|         } else if (type == 2) { |         } else if (type == 2) { | ||||||
|             val episodes = ArrayList<TvSeriesEpisode>() |             val episodes = ArrayList<TvSeriesEpisode>() | ||||||
|             val seasons = document.select("div.accordion__card") |             val seasons = document.select("div.accordion__card") | ||||||
|  | @ -175,18 +176,17 @@ class MeloMovieProvider : MainAPI() { | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             episodes.reverse() |             episodes.reverse() | ||||||
|             return TvSeriesLoadResponse( |             return newTvSeriesLoadResponse( | ||||||
|                 title, |                 title, | ||||||
|                 url, |                 url, | ||||||
|                 this.name, |  | ||||||
|                 TvType.TvSeries, |                 TvType.TvSeries, | ||||||
|                 episodes, |                 episodes | ||||||
|                 poster, |             ) { | ||||||
|                 year, |                 this.posterUrl = poster | ||||||
|                 plot, |                 this.year = year | ||||||
|                 null, |                 this.plot = plot | ||||||
|                 imdbUrlToIdNullable(imdbUrl) |                 addImdbUrl(imdbUrl) | ||||||
|             ) |             } | ||||||
|         } |         } | ||||||
|         return null |         return null | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -163,7 +163,6 @@ class PelisflixProvider : MainAPI() { | ||||||
|                 year?.toIntOrNull(), |                 year?.toIntOrNull(), | ||||||
|                 descipt2, |                 descipt2, | ||||||
|                 null, |                 null, | ||||||
|                 null, |  | ||||||
|                 rating |                 rating | ||||||
|             ) |             ) | ||||||
|         } else { |         } else { | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| package com.lagradost.cloudstream3.movieproviders | package com.lagradost.cloudstream3.movieproviders | ||||||
| 
 | 
 | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
| import com.lagradost.cloudstream3.utils.* | import com.lagradost.cloudstream3.utils.ExtractorLink | ||||||
|  | import com.lagradost.cloudstream3.utils.loadExtractor | ||||||
| import org.jsoup.nodes.Element | import org.jsoup.nodes.Element | ||||||
| import java.util.* |  | ||||||
| 
 | 
 | ||||||
| class PelisplusHDProvider:MainAPI() { | class PelisplusHDProvider:MainAPI() { | ||||||
|     override var mainUrl = "https://pelisplushd.net" |     override var mainUrl = "https://pelisplushd.net" | ||||||
|  | @ -137,7 +137,6 @@ class PelisplusHDProvider:MainAPI() { | ||||||
|                     description, |                     description, | ||||||
|                     null, |                     null, | ||||||
|                     null, |                     null, | ||||||
|                     null, |  | ||||||
|                     tags, |                     tags, | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  | @ -152,7 +151,6 @@ class PelisplusHDProvider:MainAPI() { | ||||||
|                     year, |                     year, | ||||||
|                     description, |                     description, | ||||||
|                     null, |                     null, | ||||||
|                     null, |  | ||||||
|                     tags, |                     tags, | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -160,7 +160,6 @@ class SeriesflixProvider : MainAPI() { | ||||||
|                 year?.toIntOrNull(), |                 year?.toIntOrNull(), | ||||||
|                 descipt, |                 descipt, | ||||||
|                 null, |                 null, | ||||||
|                 null, |  | ||||||
|                 rating |                 rating | ||||||
|             ) |             ) | ||||||
|         } else { |         } else { | ||||||
|  |  | ||||||
|  | @ -76,7 +76,6 @@ class VfFilmProvider : MainAPI() { | ||||||
|         val title = document?.selectFirst("div.SubTitle")?.text() |         val title = document?.selectFirst("div.SubTitle")?.text() | ||||||
|             ?: throw ErrorLoadingException("Service might be unavailable") |             ?: throw ErrorLoadingException("Service might be unavailable") | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         val year = document.select("span.Date").text()?.toIntOrNull() |         val year = document.select("span.Date").text()?.toIntOrNull() | ||||||
| 
 | 
 | ||||||
|         val rating = document.select("span.AAIco-star").text() |         val rating = document.select("span.AAIco-star").text() | ||||||
|  | @ -88,7 +87,6 @@ class VfFilmProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|         val descript = document.selectFirst("div.Description > p").text() |         val descript = document.selectFirst("div.Description > p").text() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         val players = document.select("ul.TPlayerNv > li") |         val players = document.select("ul.TPlayerNv > li") | ||||||
|         var number_player = 0 |         var number_player = 0 | ||||||
|         var found = false |         var found = false | ||||||
|  | @ -108,17 +106,17 @@ class VfFilmProvider : MainAPI() { | ||||||
| 
 | 
 | ||||||
|         val data = getDirect("$mainUrl/?trembed=$i&trid=$trid&trtype=1") |         val data = getDirect("$mainUrl/?trembed=$i&trid=$trid&trtype=1") | ||||||
| 
 | 
 | ||||||
|         return MovieLoadResponse( |         return newMovieLoadResponse( | ||||||
|             title, |             title, | ||||||
|             url, |             url, | ||||||
|             this.name, |  | ||||||
|             TvType.Movie, |             TvType.Movie, | ||||||
|             data, |             data | ||||||
|             poster, |         ) { | ||||||
|             year, |             this.posterUrl = poster | ||||||
|             descript, |             this.year = year | ||||||
|             rating, |             this.plot = descript | ||||||
|             duration |             //this.rating = rating | ||||||
|         ) |             this.duration = duration | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -160,7 +160,6 @@ class VfSerieProvider : MainAPI() { | ||||||
|             year, |             year, | ||||||
|             descript, |             descript, | ||||||
|             null, |             null, | ||||||
|             null, |  | ||||||
|             rating |             rating | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -78,7 +78,6 @@ class FrenchStreamProvider : MainAPI() { | ||||||
|                 poster, |                 poster, | ||||||
|                 date, |                 date, | ||||||
|                 description, |                 description, | ||||||
|                 null, |  | ||||||
|                 ratingAverage, |                 ratingAverage, | ||||||
|                 tagsList, |                 tagsList, | ||||||
|                 null, |                 null, | ||||||
|  |  | ||||||
|  | @ -606,13 +606,15 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|         result_recommendations_btt?.isGone = isInvalid |         result_recommendations_btt?.isGone = isInvalid | ||||||
|         result_recommendations_btt?.setOnClickListener { |         result_recommendations_btt?.setOnClickListener { | ||||||
|             if (result_overlapping_panels?.getSelectedPanel()?.ordinal == 1) { |             if (result_overlapping_panels?.getSelectedPanel()?.ordinal == 1) { | ||||||
|  |                 result_recommendations_btt?.nextFocusDownId = R.id.result_recommendations | ||||||
|                 result_overlapping_panels?.openEndPanel() |                 result_overlapping_panels?.openEndPanel() | ||||||
|             } else { |             } else { | ||||||
|  |                 result_recommendations_btt?.nextFocusDownId = R.id.result_description | ||||||
|                 result_overlapping_panels?.closePanels() |                 result_overlapping_panels?.closePanels() | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         result_overlapping_panels?.setEndPanelLockState(if (isInvalid) OverlappingPanelsLayout.LockState.CLOSE else OverlappingPanelsLayout.LockState.UNLOCKED) |         result_overlapping_panels?.setEndPanelLockState(if (isInvalid) OverlappingPanelsLayout.LockState.CLOSE else OverlappingPanelsLayout.LockState.UNLOCKED) | ||||||
|         result_recommendations.post { |         result_recommendations?.post { | ||||||
|             rec?.let { list -> |             rec?.let { list -> | ||||||
|                 (result_recommendations?.adapter as SearchAdapter?)?.updateList(list) |                 (result_recommendations?.adapter as SearchAdapter?)?.updateList(list) | ||||||
|             } |             } | ||||||
|  | @ -1337,6 +1339,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                     result_sync_loading_shimmer?.stopShimmer() |                     result_sync_loading_shimmer?.stopShimmer() | ||||||
|                     result_sync_loading_shimmer?.isVisible = false |                     result_sync_loading_shimmer?.isVisible = false | ||||||
|                     result_sync_holder?.isVisible = false |                     result_sync_holder?.isVisible = false | ||||||
|  |                     closed = true | ||||||
|                 } |                 } | ||||||
|                 is Resource.Loading -> { |                 is Resource.Loading -> { | ||||||
|                     result_sync_loading_shimmer?.startShimmer() |                     result_sync_loading_shimmer?.startShimmer() | ||||||
|  | @ -1420,6 +1423,10 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             result_series_parent?.isVisible = isSeriesVisible |             result_series_parent?.isVisible = isSeriesVisible | ||||||
|  |             if (isSeriesVisible && activity?.currentFocus?.id == R.id.result_back && context?.isTrueTvSettings() == true) { | ||||||
|  |                 result_resume_series_button?.requestFocus() | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             if (isSeriesVisible) { |             if (isSeriesVisible) { | ||||||
|                 val down = when { |                 val down = when { | ||||||
|                     result_season_button?.isVisible == true -> result_season_button |                     result_season_button?.isVisible == true -> result_season_button | ||||||
|  | @ -1634,16 +1641,13 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                     setRecommendations(d.recommendations) |                     setRecommendations(d.recommendations) | ||||||
|                     setActors(d.actors) |                     setActors(d.actors) | ||||||
| 
 | 
 | ||||||
|                     if (SettingsFragment.accountEnabled) |                     if (SettingsFragment.accountEnabled) { | ||||||
|                         if (d is AnimeLoadResponse) { |                         var isValid = false | ||||||
|                             // don't inline these variables as it will cause them to not be called |                         for ((prefix, id) in d.syncData) { | ||||||
|                             val addedMal = setMalSync(d.malId) |                             isValid = isValid || syncModel.addSync(prefix, id) | ||||||
|                             val addedAniList = setAniListSync(d.anilistId) |                         } | ||||||
|                             if ( | 
 | ||||||
|                                 addedMal |                         if (isValid) { | ||||||
|                                 || |  | ||||||
|                                 addedAniList |  | ||||||
|                             ) { |  | ||||||
|                             syncModel.updateMetaAndUser() |                             syncModel.updateMetaAndUser() | ||||||
|                             syncModel.updateSynced() |                             syncModel.updateSynced() | ||||||
|                         } else { |                         } else { | ||||||
|  | @ -1658,6 +1662,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                         result_poster?.setImage(posterImageLink) |                         result_poster?.setImage(posterImageLink) | ||||||
|                         result_poster_blur?.setImageBlur(posterImageLink, 10, 3) |                         result_poster_blur?.setImageBlur(posterImageLink, 10, 3) | ||||||
|                         //Full screen view of Poster image |                         //Full screen view of Poster image | ||||||
|  |                         if (context?.isTrueTvSettings() == false) // Poster not clickable on tv | ||||||
|                             result_poster_holder?.setOnClickListener { |                             result_poster_holder?.setOnClickListener { | ||||||
|                                 try { |                                 try { | ||||||
|                                     context?.let { ctx -> |                                     context?.let { ctx -> | ||||||
|  | @ -1680,6 +1685,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                                     logError(e) |                                     logError(e) | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|  | 
 | ||||||
|                     } else { |                     } else { | ||||||
|                         result_poster?.setImageResource(R.drawable.default_cover) |                         result_poster?.setImageResource(R.drawable.default_cover) | ||||||
|                         result_poster_blur?.setImageResource(R.drawable.default_cover) |                         result_poster_blur?.setImageResource(R.drawable.default_cover) | ||||||
|  | @ -1698,16 +1704,16 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                         if (syno.length > MAX_SYNO_LENGH) { |                         if (syno.length > MAX_SYNO_LENGH) { | ||||||
|                             syno = syno.substring(0, MAX_SYNO_LENGH) + "..." |                             syno = syno.substring(0, MAX_SYNO_LENGH) + "..." | ||||||
|                         } |                         } | ||||||
|                         result_descript.setOnClickListener { |                         result_description.setOnClickListener { | ||||||
|                             val builder: AlertDialog.Builder = |                             val builder: AlertDialog.Builder = | ||||||
|                                 AlertDialog.Builder(requireContext()) |                                 AlertDialog.Builder(requireContext()) | ||||||
|                             builder.setMessage(d.plot) |                             builder.setMessage(d.plot) | ||||||
|                                 .setTitle(if (d.type == TvType.Torrent) R.string.torrent_plot else R.string.result_plot) |                                 .setTitle(if (d.type == TvType.Torrent) R.string.torrent_plot else R.string.result_plot) | ||||||
|                                 .show() |                                 .show() | ||||||
|                         } |                         } | ||||||
|                         result_descript.text = syno |                         result_description.text = syno | ||||||
|                     } else { |                     } else { | ||||||
|                         result_descript.text = |                         result_description.text = | ||||||
|                             if (d.type == TvType.Torrent) getString(R.string.torrent_no_plot) else getString( |                             if (d.type == TvType.Torrent) getString(R.string.torrent_no_plot) else getString( | ||||||
|                                 R.string.normal_no_plot |                                 R.string.normal_no_plot | ||||||
|                             ) |                             ) | ||||||
|  | @ -1727,12 +1733,13 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                         //result_tag_holder?.visibility = GONE |                         //result_tag_holder?.visibility = GONE | ||||||
|                     } else { |                     } else { | ||||||
|                         //result_tag_holder?.visibility = VISIBLE |                         //result_tag_holder?.visibility = VISIBLE | ||||||
| 
 |                         val isOnTv = context?.isTrueTvSettings() == true | ||||||
|                         for ((index, tag) in tags.withIndex()) { |                         for ((index, tag) in tags.withIndex()) { | ||||||
|                             val viewBtt = layoutInflater.inflate(R.layout.result_tag, null) |                             val viewBtt = layoutInflater.inflate(R.layout.result_tag, null) | ||||||
|                             val btt = viewBtt.findViewById<MaterialButton>(R.id.result_tag_card) |                             val btt = viewBtt.findViewById<MaterialButton>(R.id.result_tag_card) | ||||||
|                             btt.text = tag |                             btt.text = tag | ||||||
| 
 |                             btt.isFocusable = !isOnTv | ||||||
|  |                             btt.isClickable = !isOnTv | ||||||
|                             result_tag?.addView(viewBtt, index) |                             result_tag?.addView(viewBtt, index) | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  | @ -1980,9 +1987,15 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  |                 // bloats the navigation on tv | ||||||
|  |                 if (context?.isTrueTvSettings() == false) { | ||||||
|                     result_meta_site?.setOnClickListener { |                     result_meta_site?.setOnClickListener { | ||||||
|                         it.context?.openBrowser(tempUrl) |                         it.context?.openBrowser(tempUrl) | ||||||
|                     } |                     } | ||||||
|  |                     result_meta_site?.isFocusable = true | ||||||
|  |                 } else { | ||||||
|  |                     result_meta_site?.isFocusable = false | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|                 if (restart || viewModel.result.value == null) { |                 if (restart || viewModel.result.value == null) { | ||||||
|                     //viewModel.clear() |                     //viewModel.clear() | ||||||
|  |  | ||||||
|  | @ -65,18 +65,19 @@ class SyncViewModel : ViewModel() { | ||||||
|         _currentSynced.postValue(getMissing()) |         _currentSynced.postValue(getMissing()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun setMalId(id: String?) : Boolean { |     fun addSync(idPrefix: String, id : String) : Boolean { | ||||||
|         if(syncIds[malApi.idPrefix] == id ?: return false) return false |         if(syncIds[idPrefix] == id) return false | ||||||
|         syncIds[malApi.idPrefix] = id |         Log.i(TAG, "addSync $idPrefix = $id") | ||||||
|         Log.i(TAG, "setMalId = $id") |         syncIds[idPrefix] = id | ||||||
|         return true |         return true | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fun setMalId(id: String?) : Boolean { | ||||||
|  |         return addSync(malApi.idPrefix,id ?: return false) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fun setAniListId(id: String?) : Boolean { |     fun setAniListId(id: String?) : Boolean { | ||||||
|         if(syncIds[aniListApi.idPrefix] == id ?: return false) return false |         return addSync(aniListApi.idPrefix,id ?: return false) | ||||||
|         syncIds[aniListApi.idPrefix] = id |  | ||||||
|         Log.i(TAG, "setAniListId = $id") |  | ||||||
|         return true |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     var hasAddedFromUrl: HashSet<String> = hashSetOf() |     var hasAddedFromUrl: HashSet<String> = hashSetOf() | ||||||
|  | @ -164,8 +165,9 @@ class SyncViewModel : ViewModel() { | ||||||
|         _userDataResponse.postValue(Resource.Loading()) |         _userDataResponse.postValue(Resource.Loading()) | ||||||
|         var lastError: Resource<SyncAPI.SyncStatus> = Resource.Failure(false, null, null, "No data") |         var lastError: Resource<SyncAPI.SyncStatus> = Resource.Failure(false, null, null, "No data") | ||||||
|         for ((prefix, id) in syncIds) { |         for ((prefix, id) in syncIds) { | ||||||
|             repos.firstOrNull { it.idPrefix == prefix }?.let { |             repos.firstOrNull { it.idPrefix == prefix }?.let { repo -> | ||||||
|                 val result = it.getStatus(id) |                 if(repo.hasAccount()) { | ||||||
|  |                     val result = repo.getStatus(id) | ||||||
|                     if (result is Resource.Success) { |                     if (result is Resource.Success) { | ||||||
|                         _userDataResponse.postValue(result) |                         _userDataResponse.postValue(result) | ||||||
|                         return@launch |                         return@launch | ||||||
|  | @ -174,6 +176,7 @@ class SyncViewModel : ViewModel() { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         _userDataResponse.postValue(lastError) |         _userDataResponse.postValue(lastError) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -183,8 +186,9 @@ class SyncViewModel : ViewModel() { | ||||||
|         _metaResponse.postValue(Resource.Loading()) |         _metaResponse.postValue(Resource.Loading()) | ||||||
|         var lastError: Resource<SyncAPI.SyncResult> = Resource.Failure(false, null, null, "No data") |         var lastError: Resource<SyncAPI.SyncResult> = Resource.Failure(false, null, null, "No data") | ||||||
|         for ((prefix, id) in syncIds) { |         for ((prefix, id) in syncIds) { | ||||||
|             repos.firstOrNull { it.idPrefix == prefix }?.let { |             repos.firstOrNull { it.idPrefix == prefix }?.let { repo -> | ||||||
|                 val result = it.getResult(id) |                 if(repo.hasAccount()) { | ||||||
|  |                     val result = repo.getResult(id) | ||||||
|                     if (result is Resource.Success) { |                     if (result is Resource.Success) { | ||||||
|                         _metaResponse.postValue(result) |                         _metaResponse.postValue(result) | ||||||
|                         return@launch |                         return@launch | ||||||
|  | @ -193,6 +197,7 @@ class SyncViewModel : ViewModel() { | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         _metaResponse.postValue(lastError) |         _metaResponse.postValue(lastError) | ||||||
|         setEpisodesDelta(0) |         setEpisodesDelta(0) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -352,7 +352,7 @@ | ||||||
|                                     android:layout_height="match_parent"> |                                     android:layout_height="match_parent"> | ||||||
| 
 | 
 | ||||||
|                                 <TextView |                                 <TextView | ||||||
|                                         android:id="@+id/result_descript" |                                         android:id="@+id/result_description" | ||||||
|                                         android:layout_width="match_parent" |                                         android:layout_width="match_parent" | ||||||
|                                         android:layout_height="wrap_content" |                                         android:layout_height="wrap_content" | ||||||
|                                         android:foreground="@drawable/outline_drawable" |                                         android:foreground="@drawable/outline_drawable" | ||||||
|  | @ -390,7 +390,7 @@ | ||||||
|                             android:minWidth="100dp" |                             android:minWidth="100dp" | ||||||
|                             android:nextFocusLeft="@id/result_back" |                             android:nextFocusLeft="@id/result_back" | ||||||
|                             android:nextFocusRight="@id/result_search" |                             android:nextFocusRight="@id/result_search" | ||||||
|                             android:nextFocusUp="@id/result_descript" |                             android:nextFocusUp="@id/result_description" | ||||||
| 
 | 
 | ||||||
|                             android:nextFocusDown="@id/result_play_movie" |                             android:nextFocusDown="@id/result_play_movie" | ||||||
|                             android:paddingTop="0dp" |                             android:paddingTop="0dp" | ||||||
|  | @ -751,7 +751,7 @@ | ||||||
|                                         android:layout_marginStart="0dp" |                                         android:layout_marginStart="0dp" | ||||||
|                                         android:nextFocusLeft="@id/result_episode_select" |                                         android:nextFocusLeft="@id/result_episode_select" | ||||||
|                                         android:nextFocusRight="@id/result_episode_select" |                                         android:nextFocusRight="@id/result_episode_select" | ||||||
|                                         android:nextFocusUp="@id/result_descript" |                                         android:nextFocusUp="@id/result_description" | ||||||
|                                         android:nextFocusDown="@id/result_episodes" |                                         android:nextFocusDown="@id/result_episodes" | ||||||
|                                         android:visibility="gone" |                                         android:visibility="gone" | ||||||
|                                         tools:text="Season 1" |                                         tools:text="Season 1" | ||||||
|  | @ -766,7 +766,7 @@ | ||||||
|                                         android:nextFocusLeft="@id/result_season_button" |                                         android:nextFocusLeft="@id/result_season_button" | ||||||
|                                         android:nextFocusRight="@id/result_season_button" |                                         android:nextFocusRight="@id/result_season_button" | ||||||
| 
 | 
 | ||||||
|                                         android:nextFocusUp="@id/result_descript" |                                         android:nextFocusUp="@id/result_description" | ||||||
|                                         android:nextFocusDown="@id/result_episodes" |                                         android:nextFocusDown="@id/result_episodes" | ||||||
|                                         android:visibility="gone" |                                         android:visibility="gone" | ||||||
|                                         tools:text="50-100" |                                         tools:text="50-100" | ||||||
|  | @ -781,7 +781,7 @@ | ||||||
|                                         android:nextFocusLeft="@id/result_season_button" |                                         android:nextFocusLeft="@id/result_season_button" | ||||||
|                                         android:nextFocusRight="@id/result_season_button" |                                         android:nextFocusRight="@id/result_season_button" | ||||||
| 
 | 
 | ||||||
|                                         android:nextFocusUp="@id/result_descript" |                                         android:nextFocusUp="@id/result_description" | ||||||
|                                         android:nextFocusDown="@id/result_episodes" |                                         android:nextFocusDown="@id/result_episodes" | ||||||
|                                         android:visibility="gone" |                                         android:visibility="gone" | ||||||
|                                         tools:text="Dubbed" |                                         tools:text="Dubbed" | ||||||
|  |  | ||||||
|  | @ -70,7 +70,7 @@ | ||||||
| 
 | 
 | ||||||
|             <ImageView |             <ImageView | ||||||
|                     android:nextFocusUp="@id/result_back" |                     android:nextFocusUp="@id/result_back" | ||||||
|                     android:nextFocusDown="@id/result_descript" |                     android:nextFocusDown="@id/result_description" | ||||||
|                     android:nextFocusLeft="@id/result_add_sync" |                     android:nextFocusLeft="@id/result_add_sync" | ||||||
|                     android:nextFocusRight="@id/result_open_in_browser" |                     android:nextFocusRight="@id/result_open_in_browser" | ||||||
| 
 | 
 | ||||||
|  | @ -88,7 +88,7 @@ | ||||||
| 
 | 
 | ||||||
|             <ImageView |             <ImageView | ||||||
|                     android:nextFocusUp="@id/result_back" |                     android:nextFocusUp="@id/result_back" | ||||||
|                     android:nextFocusDown="@id/result_descript" |                     android:nextFocusDown="@id/result_description" | ||||||
|                     android:nextFocusLeft="@id/result_share" |                     android:nextFocusLeft="@id/result_share" | ||||||
|                     android:nextFocusRight="@id/result_search" |                     android:nextFocusRight="@id/result_search" | ||||||
| 
 | 
 | ||||||
|  | @ -106,7 +106,7 @@ | ||||||
| 
 | 
 | ||||||
|             <ImageView |             <ImageView | ||||||
|                     android:nextFocusUp="@id/result_back" |                     android:nextFocusUp="@id/result_back" | ||||||
|                     android:nextFocusDown="@id/result_descript" |                     android:nextFocusDown="@id/result_description" | ||||||
|                     android:nextFocusLeft="@id/result_open_in_browser" |                     android:nextFocusLeft="@id/result_open_in_browser" | ||||||
|                     android:nextFocusRight="@id/result_recommendations_btt" |                     android:nextFocusRight="@id/result_recommendations_btt" | ||||||
| 
 | 
 | ||||||
|  | @ -122,9 +122,10 @@ | ||||||
|                     android:contentDescription="@string/result_open_in_browser" |                     android:contentDescription="@string/result_open_in_browser" | ||||||
|                     app:tint="?attr/textColor" /> |                     app:tint="?attr/textColor" /> | ||||||
|             <ImageView |             <ImageView | ||||||
|  |                     tools:visibility="visible" | ||||||
|                     android:visibility="gone" |                     android:visibility="gone" | ||||||
|                     android:nextFocusUp="@id/result_back" |                     android:nextFocusUp="@id/result_back" | ||||||
|                     android:nextFocusDown="@id/result_descript" |                     android:nextFocusDown="@id/result_description" | ||||||
|                     android:nextFocusLeft="@id/result_search" |                     android:nextFocusLeft="@id/result_search" | ||||||
|                     android:nextFocusRight="@id/result_bookmark_button" |                     android:nextFocusRight="@id/result_bookmark_button" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,14 +35,14 @@ | ||||||
|         <item>None</item> |         <item>None</item> | ||||||
|         <item>Google</item> |         <item>Google</item> | ||||||
|         <item>Cloudflare</item> |         <item>Cloudflare</item> | ||||||
| <!--        <item>OpenDns</item>--> |         <!--        <item>OpenDns</item>--> | ||||||
|         <item>AdGuard</item> |         <item>AdGuard</item> | ||||||
|     </array> |     </array> | ||||||
|     <array name="dns_pref_values"> |     <array name="dns_pref_values"> | ||||||
|         <item>0</item> |         <item>0</item> | ||||||
|         <item>1</item> |         <item>1</item> | ||||||
|         <item>2</item> |         <item>2</item> | ||||||
| <!--        <item>3</item>--> |         <!--        <item>3</item>--> | ||||||
|         <item>4</item> |         <item>4</item> | ||||||
|     </array> |     </array> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -401,6 +401,8 @@ | ||||||
|     <string name="sync_total_episodes_none">/??</string> |     <string name="sync_total_episodes_none">/??</string> | ||||||
|     <string name="sync_total_episodes_some" formatted="true">/%d</string> |     <string name="sync_total_episodes_some" formatted="true">/%d</string> | ||||||
|     <string name="authenticated_user" formatted="true">Authenticated %s</string> |     <string name="authenticated_user" formatted="true">Authenticated %s</string> | ||||||
|  |     <string name="authenticated_user_fail" formatted="true">Failed to authenticate to %s</string> | ||||||
|  | 
 | ||||||
|     <!-- ============ --> |     <!-- ============ --> | ||||||
|     <string name="none">None</string> |     <string name="none">None</string> | ||||||
|     <string name="normal">Normal</string> |     <string name="normal">Normal</string> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue