forked from recloudstream/cloudstream
		
	
							parent
							
								
									c2ba8dc7e4
								
							
						
					
					
						commit
						2870ad435f
					
				
					 9 changed files with 444 additions and 394 deletions
				
			
		|  | @ -281,7 +281,8 @@ object APIHolder { | |||
| 3 = restricted, must donate 30 benenes to use | ||||
|  */ | ||||
| const val PROVIDER_STATUS_KEY = "PROVIDER_STATUS_KEY" | ||||
| const val PROVIDER_STATUS_URL = "https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/providers.json" | ||||
| const val PROVIDER_STATUS_URL = | ||||
|     "https://raw.githubusercontent.com/LagradOst/CloudStream-3/master/providers.json" | ||||
| const val PROVIDER_STATUS_BETA_ONLY = 3 | ||||
| const val PROVIDER_STATUS_SLOW = 2 | ||||
| const val PROVIDER_STATUS_OK = 1 | ||||
|  | @ -540,13 +541,28 @@ class HomePageList( | |||
|     var list: List<SearchResponse> | ||||
| ) | ||||
| 
 | ||||
| enum class SearchQuality { | ||||
|     //https://en.wikipedia.org/wiki/Pirated_movie_release_types | ||||
|     Cam, | ||||
|     CamRip, | ||||
|     HdCam, | ||||
|     Telesync, // TS | ||||
|     WorkPrint, | ||||
|     Telecine, // TC | ||||
|     HQ, | ||||
|     HD, | ||||
|     BlueRay, | ||||
|     DVD, | ||||
| } | ||||
| 
 | ||||
| interface SearchResponse { | ||||
|     val name: String | ||||
|     val url: String | ||||
|     val apiName: String | ||||
|     val type: TvType? | ||||
|     val posterUrl: String? | ||||
|     val id: Int? | ||||
|     var type: TvType? | ||||
|     var posterUrl: String? | ||||
|     var id: Int? | ||||
|     var quality : SearchQuality? | ||||
| } | ||||
| 
 | ||||
| enum class ActorRole { | ||||
|  | @ -571,49 +587,53 @@ data class AnimeSearchResponse( | |||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
|     override var type: TvType?, | ||||
| 
 | ||||
|     override val posterUrl: String?, | ||||
|     override var posterUrl: String?, | ||||
|     val year: Int? = null, | ||||
|     val dubStatus: EnumSet<DubStatus>? = null, | ||||
| 
 | ||||
|     val otherName: String? = null, | ||||
|     val dubEpisodes: Int? = null, | ||||
|     val subEpisodes: Int? = null, | ||||
|     override val id: Int? = null, | ||||
|     override var id: Int? = null, | ||||
|     override var quality: SearchQuality? = null, | ||||
| ) : SearchResponse | ||||
| 
 | ||||
| data class TorrentSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
|     override var type: TvType?, | ||||
| 
 | ||||
|     override val posterUrl: String?, | ||||
|     override val id: Int? = null, | ||||
|     override var posterUrl: String?, | ||||
|     override var id: Int? = null, | ||||
|     override var quality: SearchQuality? = null, | ||||
| ) : SearchResponse | ||||
| 
 | ||||
| data class MovieSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
|     override var type: TvType?, | ||||
| 
 | ||||
|     override val posterUrl: String?, | ||||
|     override var posterUrl: String?, | ||||
|     val year: Int? = null, | ||||
|     override val id: Int? = null, | ||||
|     override var id: Int? = null, | ||||
|     override var quality: SearchQuality? = null, | ||||
| ) : SearchResponse | ||||
| 
 | ||||
| data class TvSeriesSearchResponse( | ||||
|     override val name: String, | ||||
|     override val url: String, | ||||
|     override val apiName: String, | ||||
|     override val type: TvType, | ||||
|     override var type: TvType?, | ||||
| 
 | ||||
|     override val posterUrl: String?, | ||||
|     override var posterUrl: String?, | ||||
|     val year: Int?, | ||||
|     val episodes: Int?, | ||||
|     override val id: Int? = null, | ||||
|     override var id: Int? = null, | ||||
|     override var quality: SearchQuality? = null, | ||||
| ) : SearchResponse | ||||
| 
 | ||||
| interface LoadResponse { | ||||
|  | @ -630,6 +650,7 @@ interface LoadResponse { | |||
|     val trailerUrl: String? | ||||
|     var recommendations: List<SearchResponse>? | ||||
|     var actors: List<ActorData>? | ||||
|     var comingSoon: Boolean | ||||
| 
 | ||||
|     companion object { | ||||
|         @JvmName("addActorNames") | ||||
|  | @ -715,6 +736,7 @@ data class TorrentLoadResponse( | |||
|     override var trailerUrl: String? = null, | ||||
|     override var recommendations: List<SearchResponse>? = null, | ||||
|     override var actors: List<ActorData>? = null, | ||||
|     override var comingSoon: Boolean = false, | ||||
| ) : LoadResponse | ||||
| 
 | ||||
| data class AnimeLoadResponse( | ||||
|  | @ -742,6 +764,7 @@ data class AnimeLoadResponse( | |||
|     override var trailerUrl: String? = null, | ||||
|     override var recommendations: List<SearchResponse>? = null, | ||||
|     override var actors: List<ActorData>? = null, | ||||
|     override var comingSoon: Boolean = false, | ||||
| ) : LoadResponse | ||||
| 
 | ||||
| fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<AnimeEpisode>?) { | ||||
|  | @ -753,13 +776,31 @@ fun MainAPI.newAnimeLoadResponse( | |||
|     name: String, | ||||
|     url: String, | ||||
|     type: TvType, | ||||
|     initializer: AnimeLoadResponse.() -> Unit = { } | ||||
|     comingSoonIfNone : Boolean, | ||||
|     initializer: AnimeLoadResponse.() -> Unit = { }, | ||||
| ): AnimeLoadResponse { | ||||
|     val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type) | ||||
|     builder.initializer() | ||||
|     if(comingSoonIfNone) { | ||||
|         builder.comingSoon = true | ||||
|         for (key in builder.episodes.keys) | ||||
|             if(!builder.episodes[key].isNullOrEmpty()) { | ||||
|                 builder.comingSoon = false | ||||
|                 break | ||||
|             } | ||||
|     } | ||||
|     return builder | ||||
| } | ||||
| 
 | ||||
| fun MainAPI.newAnimeLoadResponse( | ||||
|     name: String, | ||||
|     url: String, | ||||
|     type: TvType, | ||||
|     initializer: AnimeLoadResponse.() -> Unit = { }, | ||||
| ): AnimeLoadResponse { | ||||
|     return newAnimeLoadResponse(name, url, type, true, initializer) | ||||
| } | ||||
| 
 | ||||
| data class MovieLoadResponse( | ||||
|     override var name: String, | ||||
|     override var url: String, | ||||
|  | @ -778,6 +819,7 @@ data class MovieLoadResponse( | |||
|     override var trailerUrl: String? = null, | ||||
|     override var recommendations: List<SearchResponse>? = null, | ||||
|     override var actors: List<ActorData>? = null, | ||||
|     override var comingSoon: Boolean = false, | ||||
| ) : LoadResponse | ||||
| 
 | ||||
| fun MainAPI.newMovieLoadResponse( | ||||
|  | @ -792,7 +834,8 @@ fun MainAPI.newMovieLoadResponse( | |||
|         url = url, | ||||
|         apiName = this.name, | ||||
|         type = type, | ||||
|         dataUrl = dataUrl | ||||
|         dataUrl = dataUrl, | ||||
|         comingSoon = dataUrl.isBlank() | ||||
|     ) | ||||
|     builder.initializer() | ||||
|     return builder | ||||
|  | @ -828,6 +871,7 @@ data class TvSeriesLoadResponse( | |||
|     override var trailerUrl: String? = null, | ||||
|     override var recommendations: List<SearchResponse>? = null, | ||||
|     override var actors: List<ActorData>? = null, | ||||
|     override var comingSoon: Boolean = false, | ||||
| ) : LoadResponse | ||||
| 
 | ||||
| fun MainAPI.newTvSeriesLoadResponse( | ||||
|  | @ -842,7 +886,8 @@ fun MainAPI.newTvSeriesLoadResponse( | |||
|         url = url, | ||||
|         apiName = this.name, | ||||
|         type = type, | ||||
|         episodes = episodes | ||||
|         episodes = episodes, | ||||
|         comingSoon = episodes.isEmpty(), | ||||
|     ) | ||||
|     builder.initializer() | ||||
|     return builder | ||||
|  |  | |||
|  | @ -157,7 +157,7 @@ open class SflixProvider() : MainAPI() { | |||
|         val dataId = details.attr("data-id") | ||||
|         val id = if (dataId.isNullOrEmpty()) | ||||
|             idRegex.find(url)?.groupValues?.get(1) | ||||
|                 ?: throw RuntimeException("Unable to get id from '$url'") | ||||
|                 ?: throw ErrorLoadingException("Unable to get id from '$url'") | ||||
|         else dataId | ||||
| 
 | ||||
|         val recommendations = | ||||
|  | @ -199,6 +199,8 @@ open class SflixProvider() : MainAPI() { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             val comingSoon = sourceIds.isEmpty() | ||||
| 
 | ||||
|             return newMovieLoadResponse(title, url, TvType.Movie, sourceIds.toJson()) { | ||||
|                 this.year = year | ||||
|                 this.posterUrl = posterUrl | ||||
|  | @ -207,6 +209,7 @@ open class SflixProvider() : MainAPI() { | |||
|                 addActors(cast) | ||||
|                 this.tags = tags | ||||
|                 this.recommendations = recommendations | ||||
|                 this.comingSoon = comingSoon | ||||
|             } | ||||
|         } else { | ||||
|             val seasonsDocument = app.get("$mainUrl/ajax/v2/tv/seasons/$id").document | ||||
|  | @ -252,6 +255,7 @@ open class SflixProvider() : MainAPI() { | |||
|                     ) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { | ||||
|                 this.posterUrl = posterUrl | ||||
|                 this.year = year | ||||
|  |  | |||
|  | @ -1375,7 +1375,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|                                         val sourceDialog = sourceBuilder.create() | ||||
|                                         sourceDialog.show() | ||||
| 
 | ||||
|                                         sourceDialog.findViewById<ImageView?>(R.id.imgPoster)?.apply { | ||||
|                                         sourceDialog.findViewById<ImageView?>(R.id.imgPoster) | ||||
|                                             ?.apply { | ||||
|                                                 setImageBitmap(bitmap) | ||||
|                                                 setOnClickListener { | ||||
|                                                     sourceDialog.dismissSafe() | ||||
|  | @ -1423,6 +1424,11 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio | |||
|                         //result_tag_holder?.visibility = GONE | ||||
|                         // result_status.visibility = GONE | ||||
| 
 | ||||
|                         d.comingSoon.let { soon -> | ||||
|                             result_coming_soon?.isVisible = soon | ||||
|                             result_data_holder?.isGone = soon | ||||
|                         } | ||||
| 
 | ||||
|                         val tags = d.tags | ||||
|                         if (tags.isNullOrEmpty()) { | ||||
|                             //result_tag_holder?.visibility = GONE | ||||
|  |  | |||
|  | @ -150,7 +150,7 @@ object SearchResultBuilder { | |||
| 
 | ||||
|                 playImg?.visibility = View.VISIBLE | ||||
| 
 | ||||
|                 if (!card.type.isMovieType()) { | ||||
|                 if (card.type?.isMovieType() == false) { | ||||
|                     cardText?.text = | ||||
|                         cardText?.context?.getNameFull(card.name, card.episode, card.season) | ||||
|                 } | ||||
|  |  | |||
|  | @ -4,11 +4,8 @@ import androidx.lifecycle.LiveData | |||
| import androidx.lifecycle.MutableLiveData | ||||
| import androidx.lifecycle.ViewModel | ||||
| import androidx.lifecycle.viewModelScope | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.apis | ||||
| import com.lagradost.cloudstream3.ErrorLoadingException | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.TvType | ||||
| import com.lagradost.cloudstream3.apmap | ||||
| import com.lagradost.cloudstream3.mvvm.Resource | ||||
| import com.lagradost.cloudstream3.mvvm.safeApiCall | ||||
| import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.SyncApis | ||||
|  | @ -54,9 +51,10 @@ class SearchViewModel : ViewModel() { | |||
|         override val name: String, | ||||
|         override val url: String, | ||||
|         override val apiName: String, | ||||
|         override val type: TvType?, | ||||
|         override val posterUrl: String?, | ||||
|         override val id: Int?, | ||||
|         override var type: TvType?, | ||||
|         override var posterUrl: String?, | ||||
|         override var id: Int?, | ||||
|         override var quality: SearchQuality? = null | ||||
|     ) : SearchResponse | ||||
| 
 | ||||
|     private fun SyncAPI.SyncSearchResult.toSearchResponse(): SyncSearchResultSearchResponse { | ||||
|  |  | |||
|  | @ -63,7 +63,7 @@ object AppUtils { | |||
|         context: Context, | ||||
|         card: DataStoreHelper.ResumeWatchingResult | ||||
|     ): WatchNextProgram { | ||||
|         val isSeries = !card.type.isMovieType() | ||||
|         val isSeries = card.type?.isMovieType() == false | ||||
|         val title = if (isSeries) { | ||||
|             context.getNameFull(card.name, card.episode, card.season) | ||||
|         } else { | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys | |||
| import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey | ||||
| import com.lagradost.cloudstream3.AcraApplication.Companion.setKey | ||||
| import com.lagradost.cloudstream3.DubStatus | ||||
| import com.lagradost.cloudstream3.SearchQuality | ||||
| import com.lagradost.cloudstream3.SearchResponse | ||||
| import com.lagradost.cloudstream3.TvType | ||||
| import com.lagradost.cloudstream3.ui.WatchType | ||||
|  | @ -33,31 +34,33 @@ object DataStoreHelper { | |||
|     } | ||||
| 
 | ||||
|     data class BookmarkedData( | ||||
|        @JsonProperty("id") override val id: Int?, | ||||
|         @JsonProperty("id") override var id: Int?, | ||||
|         @JsonProperty("bookmarkedTime") val bookmarkedTime: Long, | ||||
|         @JsonProperty("latestUpdatedTime") val latestUpdatedTime: Long, | ||||
|         @JsonProperty("name") override val name: String, | ||||
|         @JsonProperty("url") override val url: String, | ||||
|         @JsonProperty("apiName") override val apiName: String, | ||||
|        @JsonProperty("type") override val type: TvType, | ||||
|        @JsonProperty("posterUrl") override val posterUrl: String?, | ||||
|         @JsonProperty("type") override var type: TvType? = null, | ||||
|         @JsonProperty("posterUrl") override var posterUrl: String?, | ||||
|         @JsonProperty("year") val year: Int?, | ||||
|         @JsonProperty("quality") override var quality: SearchQuality? = null | ||||
|     ) : SearchResponse | ||||
| 
 | ||||
|     data class ResumeWatchingResult( | ||||
|         @JsonProperty("name") override val name: String, | ||||
|         @JsonProperty("url") override val url: String, | ||||
|         @JsonProperty("apiName") override val apiName: String, | ||||
|         @JsonProperty("type") override val type: TvType, | ||||
|         @JsonProperty("posterUrl") override val posterUrl: String?, | ||||
|         @JsonProperty("type") override var type: TvType? = null, | ||||
|         @JsonProperty("posterUrl") override var posterUrl: String?, | ||||
| 
 | ||||
|         @JsonProperty("watchPos") val watchPos: PosDur?, | ||||
| 
 | ||||
|         @JsonProperty("id") override val id: Int?, | ||||
|         @JsonProperty("id") override var id: Int?, | ||||
|         @JsonProperty("parentId") val parentId: Int?, | ||||
|         @JsonProperty("episode") val episode: Int?, | ||||
|         @JsonProperty("season") val season: Int?, | ||||
|         @JsonProperty("isFromDownload") val isFromDownload: Boolean, | ||||
|         @JsonProperty("quality") override var quality: SearchQuality? = null | ||||
|     ) : SearchResponse | ||||
| 
 | ||||
|     var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION | ||||
|  |  | |||
|  | @ -459,6 +459,24 @@ | |||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                     <TextView | ||||
|                             android:paddingTop="50dp" | ||||
|                             android:visibility="gone" | ||||
|                             android:textColor="?attr/textColor" | ||||
|                             android:id="@+id/result_coming_soon" | ||||
|                             android:textSize="20sp" | ||||
|                             android:gravity="center" | ||||
|                             android:textStyle="bold" | ||||
|                             android:layout_gravity="center" | ||||
|                             android:text="@string/coming_soon" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" /> | ||||
| 
 | ||||
|                     <LinearLayout | ||||
|                             android:orientation="vertical" | ||||
|                             android:id="@+id/result_data_holder" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content"> | ||||
|                         <com.google.android.material.button.MaterialButton | ||||
|                                 android:visibility="gone" | ||||
|                                 android:text="@string/add_sync" | ||||
|  | @ -706,44 +724,6 @@ | |||
|                                     android:layout_height="wrap_content" | ||||
|                                     tools:ignore="RtlSymmetry" /> | ||||
|                         </LinearLayout> | ||||
|                     <!--<TextView | ||||
|                             android:visibility="gone" | ||||
|                             android:drawableLeft="@drawable/ic_baseline_play_arrow_24" | ||||
|                             android:gravity="center_vertical" | ||||
|                             android:textSize="20sp" | ||||
|                             android:textColor="?attr/textColor" | ||||
|                             android:text="More like this" | ||||
|                             android:layout_width="wrap_content" android:layout_height="60dp"> | ||||
|                     </TextView> | ||||
|                     <com.google.android.material.tabs.TabLayout | ||||
|                             android:visibility="gone" | ||||
|                             android:layout_width="match_parent" | ||||
|                             android:layout_height="wrap_content" | ||||
|                             app:tabTextColor="?attr/textColor" | ||||
|                             android:foreground="@color/transparent" | ||||
|                             android:backgroundTint="@color/transparent" | ||||
|                             app:tabIndicatorGravity="top" | ||||
|                             android:textAllCaps="false" | ||||
| 
 | ||||
|                             app:tabIconTint="?attr/textColor" | ||||
|                             app:tabIndicatorColor="?attr/textColor" | ||||
|                             android:id="@+id/result_tabs" | ||||
|                             app:tabGravity="start"> | ||||
|                         <com.google.android.material.tabs.TabItem | ||||
|                                 android:text="Episodes" | ||||
|                                 android:icon="@null" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content"> | ||||
|                         </com.google.android.material.tabs.TabItem> | ||||
|                         <com.google.android.material.tabs.TabItem | ||||
|                                 android:text="Sync" | ||||
|                                 android:icon="@null" | ||||
|                                 android:layout_width="wrap_content" | ||||
|                                 android:layout_height="wrap_content"> | ||||
| 
 | ||||
|                         </com.google.android.material.tabs.TabItem> | ||||
|                     </com.google.android.material.tabs.TabLayout>--> | ||||
| 
 | ||||
| 
 | ||||
|                         <LinearLayout | ||||
|                                 android:id="@+id/result_episodes_tab" | ||||
|  | @ -861,6 +841,8 @@ | |||
|                                     android:layout_height="wrap_content" /> | ||||
|                         </LinearLayout> | ||||
|                     </LinearLayout> | ||||
| 
 | ||||
|                 </LinearLayout> | ||||
|             </LinearLayout> | ||||
|         </androidx.core.widget.NestedScrollView> | ||||
| 
 | ||||
|  |  | |||
|  | @ -429,5 +429,17 @@ | |||
|     <string name="actor_background">Background</string> | ||||
| 
 | ||||
|     <string name="home_source">Source</string> | ||||
| 
 | ||||
|     <string name="coming_soon">Coming soon…</string> | ||||
|     <string name="quality_cam">Cam</string> | ||||
|     <string name="quality_cam_rip">Cam</string> | ||||
|     <string name="quality_cam_hd">Cam</string> | ||||
|     <string name="quality_hq">HQ</string> | ||||
|     <string name="quality_hd">HD</string> | ||||
|     <string name="quality_ts">TS</string> | ||||
|     <string name="quality_tc">TC</string> | ||||
|     <string name="quality_blueray">BlueRay</string> | ||||
|     <string name="quality_workprint">WP</string> | ||||
|     <string name="quality_dvd">DVD</string> | ||||
|     <string name="poster_image">Poster Image</string> | ||||
| </resources> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue