add newly added title to HomeFragment
* add support for season_list to crunchyroll parser
This commit is contained in:
		| @ -74,7 +74,10 @@ object Crunchyroll { | ||||
|         return@runBlocking false | ||||
|     } | ||||
|  | ||||
|     // TODO get/post difference | ||||
|     /** | ||||
|      * Requests: get, post, delete | ||||
|      */ | ||||
|  | ||||
|     private suspend fun request( | ||||
|         endpoint: String, | ||||
|         params: Parameters = listOf(), | ||||
| @ -83,7 +86,6 @@ object Crunchyroll { | ||||
|         val path = if (url.isEmpty()) "$baseUrl$endpoint" else url | ||||
|  | ||||
|         // TODO before sending a request, make sure the accessToken is not expired | ||||
|  | ||||
|         return@coroutineScope (Dispatchers.IO) { | ||||
|             val (request, response, result) = Fuel.get(path, params) | ||||
|                 .header("Authorization", "$tokenType $accessToken") | ||||
| @ -168,7 +170,7 @@ object Crunchyroll { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Main media functions: browse, search, series, season, episodes, playback | ||||
|      * General element/media functions: browse, search, objects, season_list | ||||
|      */ | ||||
|  | ||||
|     // TODO locale de-DE, categories | ||||
| @ -190,7 +192,7 @@ object Crunchyroll { | ||||
|         val noneOptParams = listOf("sort_by" to sortBy.str, "start" to start, "n" to n) | ||||
|  | ||||
|         // if a season tag is present add it to the parameters | ||||
|         val parameters = if (seasonTag.isEmpty()) { | ||||
|         val parameters = if (seasonTag.isNotEmpty()) { | ||||
|             concatenate(noneOptParams, listOf("season_tag" to seasonTag)) | ||||
|         } else { | ||||
|             noneOptParams | ||||
| @ -231,7 +233,7 @@ object Crunchyroll { | ||||
|      * @param objects The object IDs as list of Strings | ||||
|      * @return A **[Collection]** of Panels | ||||
|      */ | ||||
|     suspend fun objects(objects: List<String>): Collection { | ||||
|     suspend fun objects(objects: List<String>): Collection<Item> { | ||||
|         val episodesEndpoint = "/cms/v2/DE/M3/crunchyroll/objects/${objects.joinToString(",")}" | ||||
|         val parameters = listOf( | ||||
|             "locale" to locale, | ||||
| @ -247,6 +249,25 @@ object Crunchyroll { | ||||
|         } ?: NoneCollection | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all available seasons as **[SeasonListItem]**. | ||||
|      */ | ||||
|     @Suppress("unused") | ||||
|     suspend fun seasonList(): DiscSeasonList { | ||||
|         val seasonListEndpoint = "/content/v1/season_list" | ||||
|         val parameters = listOf("locale" to locale) | ||||
|  | ||||
|         val result = request(seasonListEndpoint, parameters) | ||||
|  | ||||
|         return result.component1()?.obj()?.let { | ||||
|             json.decodeFromString(it.toString()) | ||||
|         } ?: NoneDiscSeasonList | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Main media functions: series, season, episodes, playback | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * series id == crunchyroll id? | ||||
|      */ | ||||
|  | ||||
| @ -15,44 +15,25 @@ enum class SortBy(val str: String) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * search, browse, watchlist data types (all collections) | ||||
|  * search, browse, DiscSeasonList, Watchlist, ContinueWatchingList data types all use Collection | ||||
|  */ | ||||
|  | ||||
| // TODO make generic | ||||
| @Serializable | ||||
| data class Collection( | ||||
| data class Collection<T>( | ||||
|     @SerialName("total") val total: Int, | ||||
|     @SerialName("items") val items: List<Item> | ||||
|     @SerialName("items") val items: List<T> | ||||
| ) | ||||
|  | ||||
| // TODO don't use aliases | ||||
| typealias SearchCollection = Collection | ||||
| typealias BrowseResult = Collection | ||||
| typealias Watchlist = Collection | ||||
| typealias SearchResult = Collection<SearchCollection> | ||||
| typealias SearchCollection = Collection<Item> | ||||
| typealias BrowseResult = Collection<Item> | ||||
| typealias DiscSeasonList = Collection<SeasonListItem> | ||||
| typealias Watchlist = Collection<Item> | ||||
| typealias ContinueWatchingList = Collection<ContinueWatchingItem> | ||||
|  | ||||
| @Serializable | ||||
| data class SearchResult( | ||||
|     @SerialName("total") val total: Int, | ||||
|     @SerialName("items") val items: List<SearchCollection> | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class ContinueWatchingList( | ||||
|     @SerialName("total") val total: Int, | ||||
|     @SerialName("items") val items: List<ContinueWatchingItem> | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class ContinueWatchingItem( | ||||
|     @SerialName("panel") val panel: EpisodePanel, | ||||
|     @SerialName("new") val new: Boolean, | ||||
|     @SerialName("new_content") val newContent: Boolean, | ||||
|     // not present in up_next_account's continue_watching_item | ||||
| //    @SerialName("is_favorite") val isFavorite: Boolean, | ||||
| //    @SerialName("never_watched") val neverWatched: Boolean, | ||||
| //    @SerialName("completion_status") val completionStatus: Boolean, | ||||
|     @SerialName("playhead") val playhead: Int, | ||||
| ) | ||||
| /** | ||||
|  * panel data classes | ||||
|  */ | ||||
|  | ||||
| // the data class Item is used in browse and search | ||||
| // TODO rename to MediaPanel | ||||
| @ -64,7 +45,45 @@ data class Item( | ||||
|     val channel_id: String, | ||||
|     val description: String, | ||||
|     val images: Images | ||||
|     // TODO metadata etc. | ||||
|     // TODO series_metadata etc. | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class Images(val poster_tall: List<List<Poster>>, val poster_wide: List<List<Poster>>) | ||||
| // crunchyroll why? | ||||
|  | ||||
| @Serializable | ||||
| data class Poster(val height: Int, val width: Int, val source: String, val type: String) | ||||
|  | ||||
| /** | ||||
|  * season list data classes | ||||
|  */ | ||||
| @Serializable | ||||
| data class SeasonListItem( | ||||
|     @SerialName("id") val id: String, | ||||
|     @SerialName("localization") val localization: SeasonListLocalization | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class SeasonListLocalization( | ||||
|     @SerialName("title") val title: String, | ||||
|     @SerialName("description") val description: String, | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * continue_watching_item data classes | ||||
|  */ | ||||
|  | ||||
| @Serializable | ||||
| data class ContinueWatchingItem( | ||||
|     @SerialName("panel") val panel: EpisodePanel, | ||||
|     @SerialName("new") val new: Boolean, | ||||
|     @SerialName("new_content") val newContent: Boolean, | ||||
|     // not present in up_next_account's continue_watching_item | ||||
| //    @SerialName("is_favorite") val isFavorite: Boolean, | ||||
| //    @SerialName("never_watched") val neverWatched: Boolean, | ||||
| //    @SerialName("completion_status") val completionStatus: Boolean, | ||||
|     @SerialName("playhead") val playhead: Int, | ||||
| ) | ||||
|  | ||||
| // EpisodePanel is used in ContinueWatchingItem | ||||
| @ -79,13 +98,6 @@ data class EpisodePanel( | ||||
|     @SerialName("episode_metadata") val episodeMetadata: EpisodeMetadata, | ||||
| ) | ||||
|  | ||||
| @Serializable | ||||
| data class Images(val poster_tall: List<List<Poster>>, val poster_wide: List<List<Poster>>) | ||||
| // crunchyroll why? | ||||
|  | ||||
| @Serializable | ||||
| data class Poster(val height: Int, val width: Int, val source: String, val type: String) | ||||
|  | ||||
| @Serializable | ||||
| data class EpisodeMetadata( | ||||
|     @SerialName("series_id") val seriesId: String, | ||||
| @ -93,9 +105,11 @@ data class EpisodeMetadata( | ||||
| ) | ||||
|  | ||||
| val NoneItem = Item("", "", "", "", "", Images(emptyList(), emptyList())) | ||||
| val NoneCollection = Collection(0, emptyList()) | ||||
| val NoneCollection = Collection<Item>(0, emptyList()) | ||||
| val NoneSearchResult = SearchResult(0, emptyList()) | ||||
| val NoneBrowseResult = BrowseResult(0, emptyList()) | ||||
| val NoneDiscSeasonList = DiscSeasonList(0, emptyList()) | ||||
| val NoneWatchlist = Watchlist(0, emptyList()) | ||||
| val NoneContinueWatchingList = ContinueWatchingList(0, emptyList()) | ||||
|  | ||||
| /** | ||||
|  | ||||
| @ -11,6 +11,7 @@ import kotlinx.coroutines.joinAll | ||||
| import kotlinx.coroutines.launch | ||||
| import org.mosad.teapod.databinding.FragmentHomeBinding | ||||
| import org.mosad.teapod.parser.crunchyroll.Crunchyroll | ||||
| import org.mosad.teapod.parser.crunchyroll.SortBy | ||||
| import org.mosad.teapod.util.ItemMedia | ||||
| import org.mosad.teapod.util.adapter.MediaItemAdapter | ||||
| import org.mosad.teapod.util.decoration.MediaItemDecoration | ||||
| @ -87,9 +88,17 @@ class HomeFragment : Fragment() { | ||||
|         } | ||||
|         asyncJobList.add(watchlistJob) | ||||
|  | ||||
|         // new titles TODO | ||||
| //        adapterNewTitles = MediaItemAdapter(AoDParser.newTitlesList) | ||||
| //        binding.recyclerNewTitles.adapter = adapterNewTitles | ||||
|         // new simulcasts TODO replace with new titles? browse(sortBy = SortBy.NEWLY_ADDED, n = 50) | ||||
|         val simulcastsJob = lifecycleScope.launch { | ||||
| //            val latestSeasonTag = Crunchyroll.seasonList().items.first().id | ||||
| //            val newSimulcasts = Crunchyroll.browse(seasonTag = latestSeasonTag, n = 50) | ||||
|  | ||||
|             val newSimulcasts = Crunchyroll.browse(sortBy = SortBy.NEWLY_ADDED, n = 50) | ||||
|  | ||||
|             adapterNewTitles = MediaItemAdapter(newSimulcasts.toItemMediaList()) | ||||
|             binding.recyclerNewTitles.adapter = adapterNewTitles | ||||
|         } | ||||
|         asyncJobList.add(simulcastsJob) | ||||
|  | ||||
|         // top ten TODO | ||||
| //        adapterTopTen = MediaItemAdapter(AoDParser.topTenList) | ||||
| @ -135,10 +144,10 @@ class HomeFragment : Fragment() { | ||||
|             activity?.showFragment(MediaFragment(id)) | ||||
|         } | ||||
|  | ||||
| //        adapterNewTitles.onItemClick = { id, _ -> | ||||
| //            activity?.showFragment(MediaFragment("")) //(mediaId)) | ||||
| //        } | ||||
| // | ||||
|         adapterNewTitles.onItemClick = { id, _ -> | ||||
|             activity?.showFragment(MediaFragment(id)) | ||||
|         } | ||||
|  | ||||
| //        adapterTopTen.onItemClick = { id, _ -> | ||||
| //            activity?.showFragment(MediaFragment("")) //(mediaId)) | ||||
| //        } | ||||
|  | ||||
| @ -2,7 +2,9 @@ package org.mosad.teapod.util | ||||
|  | ||||
| import android.widget.TextView | ||||
| import org.mosad.teapod.parser.crunchyroll.Collection | ||||
| import org.mosad.teapod.parser.crunchyroll.ContinueWatchingItem | ||||
| import org.mosad.teapod.parser.crunchyroll.ContinueWatchingList | ||||
| import org.mosad.teapod.parser.crunchyroll.Item | ||||
|  | ||||
| fun TextView.setDrawableTop(drawable: Int) { | ||||
|     this.setCompoundDrawablesWithIntrinsicBounds(0, drawable, 0, 0) | ||||
| @ -13,16 +15,15 @@ fun <T> concatenate(vararg lists: List<T>): List<T> { | ||||
| } | ||||
|  | ||||
| // TODO move to correct location | ||||
| fun Collection.toItemMediaList(): List<ItemMedia> { | ||||
| fun Collection<Item>.toItemMediaList(): List<ItemMedia> { | ||||
|     return this.items.map { | ||||
|         ItemMedia(it.id, it.title, it.images.poster_wide[0][0].source) | ||||
|     } | ||||
| } | ||||
|  | ||||
| fun ContinueWatchingList.toItemMediaList(): List<ItemMedia> { | ||||
| @JvmName("toItemMediaListContinueWatchingItem") | ||||
| fun Collection<ContinueWatchingItem>.toItemMediaList(): List<ItemMedia> { | ||||
|     return this.items.map { | ||||
|         // TODO add season and episode to title | ||||
|         ItemMedia(it.panel.episodeMetadata.seriesId, it.panel.title, it.panel.images.thumbnail[0][0].source) | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user