diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index b09d5d3c..27fe3b4d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -143,6 +143,8 @@ interface LoadResponse { } data class AnimeLoadResponse( + val engName: String?, + val japName: String?, override val name: String, override val url: String, override val apiName: String, @@ -151,9 +153,8 @@ data class AnimeLoadResponse( override val posterUrl: String?, override val year: Int?, - val dubEpisodes: ArrayList?, - val subEpisodes: ArrayList?, - val otherName: String?, + val dubEpisodes: ArrayList?, + val subEpisodes: ArrayList?, val showStatus: ShowStatus?, val tags: ArrayList?, diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt index 687fa854..5b35d5f7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt @@ -5,11 +5,21 @@ import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import java.net.URLEncoder import java.util.* +import kotlin.collections.ArrayList class ShiroProvider : MainAPI() { companion object { var token: String? = null + + fun getType(t: String): TvType { + return when (t) { + "TV" -> TvType.Anime + "OVA" -> TvType.ONA + "movie" -> TvType.Movie + else -> TvType.Anime + } + } } fun autoLoadToken(): Boolean { @@ -45,7 +55,7 @@ class ShiroProvider : MainAPI() { @JsonProperty("episodeCount") val episodeCount: String, @JsonProperty("language") val language: String, @JsonProperty("type") val type: String, - @JsonProperty("year") val year: String, + @JsonProperty("year") val year: String?, @JsonProperty("canonicalTitle") val canonicalTitle: String, @JsonProperty("english") val english: String?, ) @@ -72,51 +82,121 @@ class ShiroProvider : MainAPI() { @JsonProperty("status") val status: String, ) + data class ShiroVideo( + @JsonProperty("video_id") val video_id: String, + @JsonProperty("host") val host: String, + ) + + data class ShiroEpisodes( + @JsonProperty("anime") val anime: AnimePageData?, + @JsonProperty("anime_slug") val anime_slug: String, + @JsonProperty("create") val create: String, + @JsonProperty("dayOfTheWeek") val dayOfTheWeek: String, + @JsonProperty("episode_number") val episode_number: Int, + @JsonProperty("slug") val slug: String, + @JsonProperty("update") val update: String, + @JsonProperty("_id") val _id: String, + @JsonProperty("videos") val videos: List, + ) + + data class AnimePageData( + @JsonProperty("banner") val banner: String?, + @JsonProperty("canonicalTitle") val canonicalTitle: String?, + @JsonProperty("episodeCount") val episodeCount: String, + @JsonProperty("genres") val genres: List?, + @JsonProperty("image") val image: String, + @JsonProperty("japanese") val japanese: String?, + @JsonProperty("english") val english: String?, + @JsonProperty("language") val language: String, + @JsonProperty("name") val name: String, + @JsonProperty("slug") val slug: String, + @JsonProperty("synopsis") val synopsis: String, + @JsonProperty("type") val type: String?, + @JsonProperty("views") val views: Int?, + @JsonProperty("year") val year: String?, + @JsonProperty("_id") val _id: String, + @JsonProperty("episodes") var episodes: List?, + @JsonProperty("synonyms") var synonyms: List?, + @JsonProperty("status") val status: String?, + @JsonProperty("schedule") val schedule: String?, + ) + + data class AnimePage( + @JsonProperty("data") val data: AnimePageData, + @JsonProperty("status") val status: String, + ) + override fun search(query: String): ArrayList? { - try { - if (!autoLoadToken()) return null - val returnValue: ArrayList = ArrayList() - val response = khttp.get("https://tapi.shiro.is/advanced?search=${ - URLEncoder.encode( - query, - "UTF-8" - ) - }&token=$token".replace("+", "%20")) - println(response.text) - val mapped = response.let { mapper.readValue(it.text) } - for (i in mapped.data.nav.currentPage.items) { + if (!autoLoadToken()) return null + val returnValue: ArrayList = ArrayList() + val response = khttp.get("https://tapi.shiro.is/advanced?search=${ + URLEncoder.encode( + query, + "UTF-8" + ) + }&token=$token".replace("+", "%20")) + if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR - val type = when (i.type) { - "TV" -> TvType.Anime - "OVA" -> TvType.ONA - "movie" -> TvType.Movie - else -> TvType.Anime - } - val isDubbed = i.language == "dubbed" - val set: EnumSet = EnumSet.noneOf(DubStatus::class.java) + val mapped = response.let { mapper.readValue(it.text) } + for (i in mapped.data.nav.currentPage.items) { + val type = getType(i.type) + val isDubbed = i.language == "dubbed" + val set: EnumSet = EnumSet.noneOf(DubStatus::class.java) - if (isDubbed) - set.add(DubStatus.HasDub) - else - set.add(DubStatus.HasSub) - val episodeCount = i.episodeCount.toInt() + if (isDubbed) + set.add(DubStatus.HasDub) + else + set.add(DubStatus.HasSub) + val episodeCount = i.episodeCount.toInt() - returnValue.add(AnimeSearchResponse( - i.english ?: i.canonicalTitle, - "$mainUrl/${i.slug}", - this.name, - type, - "https://cdn.shiro.is/${i.image}", - i.year.toInt(), - i.canonicalTitle, - set, - if (isDubbed) episodeCount else null, - if (!isDubbed) episodeCount else null, - )) - } - return returnValue - } catch (e: Exception) { - return null + returnValue.add(AnimeSearchResponse( + i.english ?: i.canonicalTitle, + "$mainUrl/${i.slug}", + this.name, + type, + "https://cdn.shiro.is/${i.image}", + i.year?.toIntOrNull(), + i.canonicalTitle, + set, + if (isDubbed) episodeCount else null, + if (!isDubbed) episodeCount else null, + )) } + return returnValue + } + + override fun load(url: String): Any? { + if (!autoLoadToken()) return null + val rurl = "https://tapi.shiro.is/anime/slug/${url}?token=${token}" + val response = khttp.get(rurl, timeout = 120.0) + val mapped = response.let { mapper.readValue(it.text) } + val data = mapped.data + val isDubbed = data.language == "dubbed" + val episodes = ArrayList(data.episodes ?: ArrayList()) + val status = when (data.status) { + "current" -> ShowStatus.Ongoing + "finished" -> ShowStatus.Completed + else -> null + } + + return AnimeLoadResponse( + data.english, + data.japanese, + data.canonicalTitle ?: data.name.replace("Dubbed", ""), + url, + this.name, + getType(data.type ?: ""), + "https://cdn.shiro.is/${data.image}", + data.year?.toIntOrNull(), + if (isDubbed) episodes else null, + if (!isDubbed) episodes else null, + status, + ArrayList(data.genres ?: ArrayList()), + data.synopsis, + ArrayList(data.synonyms ?: ArrayList()), + null, + null, + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt new file mode 100644 index 00000000..7e6d5e3d --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -0,0 +1,29 @@ +package com.lagradost.cloudstream3.ui.result + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.lagradost.cloudstream3.R + +class ResultFragment : Fragment() { + private lateinit var viewModel: ResultViewModel + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + viewModel = + ViewModelProvider(this).get(ResultViewModel::class.java) + + return inflater.inflate(R.layout.fragment_result, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt new file mode 100644 index 00000000..8bd77038 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -0,0 +1,7 @@ +package com.lagradost.cloudstream3.ui.result + +import androidx.lifecycle.ViewModel + +class ResultViewModel : ViewModel() { + +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 136f26c2..672da1d3 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -1,18 +1,15 @@ package com.lagradost.cloudstream3.ui.search -import android.content.DialogInterface import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView -import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.SearchView import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import androidx.recyclerview.widget.RecyclerView @@ -22,8 +19,9 @@ import com.lagradost.cloudstream3.APIHolder.getApiSettings import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.UIHelper.getGridIsCompact +import com.lagradost.cloudstream3.mvvm.Resource +import com.lagradost.cloudstream3.mvvm.observe import kotlinx.android.synthetic.main.fragment_search.* -import kotlin.concurrent.thread class SearchFragment : Fragment() { @@ -106,19 +104,7 @@ class SearchFragment : Fragment() { override fun onQueryTextSubmit(query: String): Boolean { search_exit_icon.alpha = 0f search_loading_bar.alpha = 1f - thread { - val data = allApi.search(query)//MainActivity.activeAPI.search(query) - activity?.runOnUiThread { - if (data == null) { - Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show() - } else { - (cardSpace.adapter as SearchAdapter).cardList = data - (cardSpace.adapter as SearchAdapter).notifyDataSetChanged() - } - search_exit_icon.alpha = 1f - search_loading_bar.alpha = 0f - } - } + searchViewModel.search(query) return true } @@ -127,6 +113,20 @@ class SearchFragment : Fragment() { } }) + observe(searchViewModel.searchResponse) { + when (it) { + is Resource.Success -> { + (cardSpace.adapter as SearchAdapter).cardList = it.value + (cardSpace.adapter as SearchAdapter).notifyDataSetChanged() + } + is Resource.Failure -> { + Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show() + } + } + search_exit_icon.alpha = 1f + search_loading_bar.alpha = 0f + } + main_search.onActionViewExpanded() } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt index 5f2a0757..d75cbd15 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt @@ -3,20 +3,24 @@ package com.lagradost.cloudstream3.ui.search import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.MainAPI +import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.safeApiCall +import kotlinx.coroutines.launch class SearchViewModel : ViewModel() { + val api: MainAPI = apis[0] - private val _text = MutableLiveData().apply { - value = "This is dashboard Fragment" - } - val text: LiveData = _text + private val _searchResponse: MutableLiveData>> = MutableLiveData() + val searchResponse: LiveData>> get() = _searchResponse - val api : MainAPI = apis[0] + fun search(query: String) = viewModelScope.launch { + val data = safeApiCall { + api.search(query) + } - suspend fun search(query: String) = safeApiCall { - api.search(query) + _searchResponse.postValue(data as Resource>?) } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index d8f4fdc4..5027d723 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,35 +1,42 @@ - - - - - + android:id="@+id/homeRoot" + > + - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_result.xml b/app/src/main/res/layout/fragment_result.xml new file mode 100644 index 00000000..912a5d04 --- /dev/null +++ b/app/src/main/res/layout/fragment_result.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file