diff --git a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt index c87e0c1..95ea3a4 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -48,7 +48,8 @@ object AoDParser { private var csrfToken: String = "" private var loginSuccess = false - private val mediaList = arrayListOf() // actual media (data) + private val mediaList = arrayListOf() // actual media (data) TODO remove + private val aodMediaList = arrayListOf() // actual media (data) // gui media val guiMediaList = arrayListOf() @@ -112,16 +113,38 @@ object AoDParser { * get a media by it's ID (int) * @return Media */ + @Deprecated(message = "Use getMediaById2() instead") suspend fun getMediaById(aodId: Int): Media { val media = mediaList.first { it.id == aodId } if (media.episodes.isEmpty()) { loadStreams(media).join() + + loadMediaAsync(media.id).await() } return media } + /** + * get a media by it's ID (int) + * @param aodId The AoD ID of the requested media + * @return returns a AoDMedia of type Movie or TVShow if found, else return AoDMediaNone + */ + suspend fun getMediaById2(aodId: Int): AoDMedia { + return aodMediaList.firstOrNull { it.aodId == aodId } ?: + try { + loadMediaAsync(aodId).await().apply { + aodMediaList.add(this) + } + } catch (exn:NullPointerException) { + Log.e(javaClass.name, "Error while loading media $aodId", exn) + AoDMediaNone + } + + + } + /** * get subscription info from aod website, remove "Anime-Abo" Prefix and trim */ @@ -417,6 +440,131 @@ object AoDParser { } } + private suspend fun loadMediaAsync(aodId: Int): Deferred = coroutineScope { + return@coroutineScope async (Dispatchers.IO) { + if (sessionCookies.isEmpty()) login() // TODO is this needed? + + // return none object, if login wasn't successful + if (!loginSuccess) { + Log.w(javaClass.name, "Login, was not successful.") + return@async AoDMediaNone + } + + // get the media page + val res = Jsoup.connect("$baseUrl/anime/$aodId") + .cookies(sessionCookies) + .get() + // println(res) + + if (csrfToken.isEmpty()) { + csrfToken = res.select("meta[name=csrf-token]").attr("content") + Log.d(javaClass.name, "New csrf token is $csrfToken") + } + + // playlist parsing TODO can this be async to the genral info marsing? + val besides = res.select("div.besides").first() + val aodPlaylists = besides.select("input.streamstarter_html5").map { streamstarter -> + parsePlaylistAsync( + streamstarter.attr("data-playlist"), + streamstarter.attr("data-lang") + ) + } + + /** + * generic aod media data + */ + val title = res.select("h1[itemprop=name]").text() + val description = res.select("div[itemprop=description]").text() + val posterURL = res.select("img.fullwidth-image").attr("src") + val type = when { + posterURL.contains("films") -> MediaType.MOVIE + posterURL.contains("series") -> MediaType.TVSHOW + else -> MediaType.OTHER + } + + var year = 0 + var age = 0 + res.select("table.vertical-table").select("tr").forEach { row -> + when (row.select("th").text().lowercase(Locale.ROOT)) { + "produktionsjahr" -> year = row.select("td").text().toInt() + "fsk" -> age = row.select("td").text().toInt() + } + } + + // similar titles from media page + val similar = res.select("h2:contains(Ähnliche Animes)").next().select("li").mapNotNull { + val mediaId = it.select("a.thumbs").attr("href") + .substringAfterLast("/").toIntOrNull() + val mediaImage = it.select("a.thumbs > img").attr("src") + val mediaTitle = it.select("a").text() + + if (mediaId != null) { + ItemMedia(mediaId, mediaTitle, mediaImage) + } else { + null + } + } + + /** + * additional information for episodes: + * description: a short description of the episode + * watched: indicates if the episodes has been watched + * watched callback: url to set watched in aod + */ + val episodesInfo: Map = if (type == MediaType.TVSHOW) { + res.select("div.three-box-container > div.episodebox").mapNotNull { episodeBox -> + // make sure the episode has a streaming link + if (episodeBox.select("input.streamstarter_html5").isNotEmpty()) { + val mediaId = episodeBox.select("div.flip-front").attr("id").substringAfter("-").toInt() + val episodeShortDesc = episodeBox.select("p.episodebox-shorttext").text() + val episodeWatched = episodeBox.select("div.episodebox-icons > div").hasClass("status-icon-orange") + val episodeWatchedCallback = episodeBox.select("input.streamstarter_html5").eachAttr("data-playlist").first() + + AoDEpisodeInfo(mediaId, episodeShortDesc, episodeWatched, episodeWatchedCallback) + } else { + null + } + }.associateBy { it.aodMediaId } + } else { + mapOf() + } + + // TODO make AoDPlaylist to teapod playlist + val playlist: List = aodPlaylists.awaitAll().flatMap { aodPlaylist -> + aodPlaylist.list.mapIndexed { index, episode -> + AoDEpisode( + mediaId = episode.mediaid, + title = episode.title, + description = episode.description, + shortDesc = episodesInfo[episode.mediaid]?.shortDesc ?: "", + imageURL = episode.image, + number = index, + watched = episodesInfo[episode.mediaid]?.watched ?: false, + watchedCallback = episodesInfo[episode.mediaid]?.watchedCallback ?: "", + streams = mutableListOf(Stream(episode.sources.first().file, aodPlaylist.language)) + ) + } + }.groupingBy { it.mediaId }.reduce{ _, accumulator, element -> + accumulator.copy().also { + it.streams.addAll(element.streams) + } + }.values.toList() + println("new playlist object: $playlist") + + return@async AoDMedia( + aodId = aodId, + type = type, + title = title, + shortText = description, + posterURL = posterURL, + year = year, + age = age, + similar = similar, + playlist = playlist + ) + } + } + /** * don't use Gson().fromJson() as we don't have any control over the api and it may change */ diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt index 29fed64..e9422f1 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/HomeFragment.kt @@ -96,10 +96,10 @@ class HomeFragment : Fragment() { binding.buttonPlayHighlight.setOnClickListener { // TODO get next episode lifecycleScope.launch { - val media = AoDParser.getMediaById(highlightMedia.id) + val media = AoDParser.getMediaById2(highlightMedia.id) - Log.d(javaClass.name, "Starting Player with mediaId: ${media.id}") - (activity as MainActivity).startPlayer(media.id, media.episodes.first().id) + Log.d(javaClass.name, "Starting Player with mediaId: ${media.aodId}") + (activity as MainActivity).startPlayer(media.aodId, media.playlist.first().mediaId) } } diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt index 026306f..2d8cef3 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt @@ -23,7 +23,6 @@ import org.mosad.teapod.databinding.FragmentMediaBinding import org.mosad.teapod.ui.activity.main.MainActivity import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.util.DataTypes.MediaType -import org.mosad.teapod.util.Episode import org.mosad.teapod.util.StorageController import org.mosad.teapod.util.tmdb.TMDBMovie import org.mosad.teapod.util.tmdb.TMDBApiController @@ -57,7 +56,7 @@ class MediaFragment(private val mediaId: Int) : Fragment() { binding.pagerEpisodesSimilar.offscreenPageLimit = 2 binding.pagerEpisodesSimilar.adapter = pagerAdapter TabLayoutMediator(binding.tabEpisodesSimilar, binding.pagerEpisodesSimilar) { tab, position -> - tab.text = if (model.media.type == MediaType.TVSHOW && position == 0) { + tab.text = if (model.media2.type == MediaType.TVSHOW && position == 0) { getString(R.string.episodes) } else { getString(R.string.similar_titles) @@ -76,8 +75,9 @@ class MediaFragment(private val mediaId: Int) : Fragment() { super.onResume() // update the next ep text if there is one, since it may have changed - if (model.nextEpisode.title.isNotEmpty()) { - binding.textTitle.text = model.nextEpisode.title + println(model.nextEpisodeId) + if (model.media2.getEpisodeById(model.nextEpisodeId).title.isNotEmpty()) { + binding.textTitle.text = model.media2.getEpisodeById(model.nextEpisodeId).title } } @@ -87,9 +87,9 @@ class MediaFragment(private val mediaId: Int) : Fragment() { private fun updateGUI() = with(model) { // generic gui val backdropUrl = tmdbResult?.backdropPath?.let { TMDBApiController.imageUrl + it } - ?: media.info.posterUrl + ?: media2.posterURL val posterUrl = tmdbResult?.posterPath?.let { TMDBApiController.imageUrl + it } - ?: media.info.posterUrl + ?: media2.posterURL // load poster and backdrop Glide.with(requireContext()).load(posterUrl) @@ -99,13 +99,13 @@ class MediaFragment(private val mediaId: Int) : Fragment() { .apply(RequestOptions.bitmapTransform(BlurTransformation(20, 3))) .into(binding.imageBackdrop) - binding.textTitle.text = media.info.title - binding.textYear.text = media.info.year.toString() - binding.textAge.text = media.info.age.toString() - binding.textOverview.text = media.info.shortDesc + binding.textTitle.text = media2.title + binding.textYear.text = media2.year.toString() + binding.textAge.text = media2.age.toString() + binding.textOverview.text = media2.shortText // set "my list" indicator - if (StorageController.myList.contains(media.id)) { + if (StorageController.myList.contains(media2.aodId)) { Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(binding.imageMyListAction) } else { Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(binding.imageMyListAction) @@ -116,28 +116,25 @@ class MediaFragment(private val mediaId: Int) : Fragment() { pagerAdapter.notifyDataSetChanged() // specific gui - if (media.type == MediaType.TVSHOW) { + if (media2.type == MediaType.TVSHOW) { // get next episode - nextEpisode = if (media.episodes.firstOrNull{ !it.watched } != null) { - media.episodes.first{ !it.watched } - } else { - media.episodes.first() - } + nextEpisodeId = media2.playlist.firstOrNull{ !it.watched }?.mediaId + ?: media2.playlist.first().mediaId // title is the next episodes title - binding.textTitle.text = nextEpisode.title + binding.textTitle.text = media2.getEpisodeById(nextEpisodeId).title // episodes count binding.textEpisodesOrRuntime.text = resources.getQuantityString( R.plurals.text_episodes_count, - media.info.episodesCount, - media.info.episodesCount + media2.playlist.size, + media2.playlist.size ) // episodes fragments.add(MediaFragmentEpisodes()) pagerAdapter.notifyDataSetChanged() - } else if (media.type == MediaType.MOVIE) { + } else if (media2.type == MediaType.MOVIE) { val tmdbMovie = (tmdbResult as TMDBMovie?) if (tmdbMovie?.runtime != null) { @@ -152,7 +149,7 @@ class MediaFragment(private val mediaId: Int) : Fragment() { } // if has similar titles - if (media.info.similar.isNotEmpty()) { + if (media2.similar.isNotEmpty()) { fragments.add(MediaFragmentSimilar()) pagerAdapter.notifyDataSetChanged() } @@ -168,20 +165,20 @@ class MediaFragment(private val mediaId: Int) : Fragment() { private fun initActions() = with(model) { binding.buttonPlay.setOnClickListener { - when (media.type) { - MediaType.MOVIE -> playEpisode(media.episodes.first()) - MediaType.TVSHOW -> playEpisode(nextEpisode) - else -> Log.e(javaClass.name, "Wrong Type: ${media.type}") + when (media2.type) { + MediaType.MOVIE -> playEpisode(media2.playlist.first().mediaId) + MediaType.TVSHOW -> playEpisode(nextEpisodeId) + else -> Log.e(javaClass.name, "Wrong Type: ${media2.type}") } } // add or remove media from myList binding.linearMyListAction.setOnClickListener { - if (StorageController.myList.contains(media.id)) { - StorageController.myList.remove(media.id) + if (StorageController.myList.contains(media2.aodId)) { + StorageController.myList.remove(media2.aodId) Glide.with(requireContext()).load(R.drawable.ic_baseline_add_24).into(binding.imageMyListAction) } else { - StorageController.myList.add(media.id) + StorageController.myList.add(media2.aodId) Glide.with(requireContext()).load(R.drawable.ic_baseline_check_24).into(binding.imageMyListAction) } StorageController.saveMyList(requireContext()) @@ -197,11 +194,11 @@ class MediaFragment(private val mediaId: Int) : Fragment() { * play the current episode * TODO this is also used in MediaFragmentEpisode, we should only have on implementation */ - private fun playEpisode(ep: Episode) { - (activity as MainActivity).startPlayer(model.media.id, ep.id) - Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") + private fun playEpisode(episodeId: Int) { + (activity as MainActivity).startPlayer(model.media2.aodId, episodeId) + Log.d(javaClass.name, "Started Player with episodeId: $episodeId") - model.updateNextEpisode(ep) // set the correct next episode + model.updateNextEpisode(episodeId) // set the correct next episode } /** diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt index 2a8b0fa..7a0eff9 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentEpisodes.kt @@ -10,7 +10,6 @@ import androidx.fragment.app.activityViewModels import org.mosad.teapod.ui.activity.main.MainActivity import org.mosad.teapod.ui.activity.main.viewmodel.MediaFragmentViewModel import org.mosad.teapod.databinding.FragmentMediaEpisodesBinding -import org.mosad.teapod.util.Episode import org.mosad.teapod.util.adapter.EpisodeItemAdapter class MediaFragmentEpisodes : Fragment() { @@ -28,13 +27,13 @@ class MediaFragmentEpisodes : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - adapterRecEpisodes = EpisodeItemAdapter(model.media.episodes, model.tmdbTVSeason?.episodes) + adapterRecEpisodes = EpisodeItemAdapter(model.media2.playlist, model.tmdbTVSeason?.episodes) binding.recyclerEpisodes.adapter = adapterRecEpisodes // set onItemClick only in adapter is initialized if (this::adapterRecEpisodes.isInitialized) { adapterRecEpisodes.onImageClick = { _, position -> - playEpisode(model.media.episodes[position]) + playEpisode(model.media2.playlist[position].mediaId) } } } @@ -44,18 +43,18 @@ class MediaFragmentEpisodes : Fragment() { // if adapterRecEpisodes is initialized, update the watched state for the episodes if (this::adapterRecEpisodes.isInitialized) { - model.media.episodes.forEachIndexed { index, episode -> - adapterRecEpisodes.updateWatchedState(episode.watched, index) + model.media2.playlist.forEachIndexed { index, episodeInfo -> + adapterRecEpisodes.updateWatchedState(episodeInfo.watched, index) } adapterRecEpisodes.notifyDataSetChanged() } } - private fun playEpisode(ep: Episode) { - (activity as MainActivity).startPlayer(model.media.id, ep.id) - Log.d(javaClass.name, "Started Player with episodeId: ${ep.id}") + private fun playEpisode(episodeId: Int) { + (activity as MainActivity).startPlayer(model.media2.aodId, episodeId) + Log.d(javaClass.name, "Started Player with episodeId: $episodeId") - model.updateNextEpisode(ep) // set the correct next episode + model.updateNextEpisode(episodeId) // set the correct next episode } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt index db6d519..dba70c3 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragmentSimilar.kt @@ -27,7 +27,7 @@ class MediaFragmentSimilar : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - adapterSimilar = MediaItemAdapter(model.media.info.similar) + adapterSimilar = MediaItemAdapter(model.media2.similar) binding.recyclerMediaSimilar.adapter = adapterSimilar binding.recyclerMediaSimilar.addItemDecoration(MediaItemDecoration(9)) diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt index 6e4c724..fd1f4b6 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/viewmodel/MediaFragmentViewModel.kt @@ -16,10 +16,17 @@ import org.mosad.teapod.util.tmdb.TMDBTVSeason */ class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) { - var media = Media(-1, "", MediaType.OTHER) +// var media = Media(-1, "", MediaType.OTHER) +// internal set +// var nextEpisode = Episode() +// internal set + + var media2 = AoDMediaNone internal set - var nextEpisode = Episode() + var nextEpisodeId = -1 internal set + + var tmdbResult: TMDBResult? = null // TODO rename internal set var tmdbTVSeason: TMDBTVSeason? =null @@ -33,15 +40,16 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic */ suspend fun load(mediaId: Int) { val tmdbApiController = TMDBApiController() - media = AoDParser.getMediaById(mediaId) + //media = AoDParser.getMediaById(mediaId) + media2 = AoDParser.getMediaById2(mediaId) // check if metaDB knows the title - val tmdbId: Int = if (MetaDBController.mediaList.media.contains(media.id)) { + val tmdbId: Int = if (MetaDBController.mediaList.media.contains(media2.aodId)) { // load media info from metaDB val metaDB = MetaDBController() - mediaMeta = when (media.type) { - MediaType.MOVIE -> metaDB.getMovieMetadata(media.id) - MediaType.TVSHOW -> metaDB.getTVShowMetadata(media.id) + mediaMeta = when (media2.type) { + MediaType.MOVIE -> metaDB.getMovieMetadata(media2.aodId) + MediaType.TVSHOW -> metaDB.getTVShowMetadata(media2.aodId) else -> null } @@ -49,10 +57,10 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic } else { // use tmdb search to get media info mediaMeta = null // set mediaMeta to null, if metaDB doesn't know the media - tmdbApiController.search(stripTitleInfo(media.info.title), media.type) + tmdbApiController.search(stripTitleInfo(media2.title), media2.type) } - tmdbResult = when (media.type) { + tmdbResult = when (media2.type) { MediaType.MOVIE -> tmdbApiController.getMovieDetails(tmdbId) MediaType.TVSHOW -> tmdbApiController.getTVShowDetails(tmdbId) else -> null @@ -60,27 +68,32 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic println(tmdbResult) // TODO // get season info, if metaDB knows the tv show - tmdbTVSeason = if (media.type == MediaType.TVSHOW && mediaMeta != null) { + tmdbTVSeason = if (media2.type == MediaType.TVSHOW && mediaMeta != null) { val tvShowMeta = mediaMeta as TVShowMeta tmdbApiController.getTVSeasonDetails(tvShowMeta.tmdbId, tvShowMeta.tmdbSeasonNumber) } else { null } - if (media.type == MediaType.TVSHOW) { - nextEpisode = media.episodes.firstOrNull{ !it.watched } ?: media.episodes.first() + if (media2.type == MediaType.TVSHOW) { + //nextEpisode = media.episodes.firstOrNull{ !it.watched } ?: media.episodes.first() + nextEpisodeId = media2.playlist.firstOrNull { !it.watched }?.mediaId + ?: media2.playlist.first().mediaId } } /** - * get the next episode based on episode number (the true next episode) + * get the next episode based on episodeId * if no matching is found, use first episode */ - fun updateNextEpisode(currentEp: Episode) { - if (media.type == MediaType.MOVIE) return // return if movie + fun updateNextEpisode(episodeId: Int) { + if (media2.type == MediaType.MOVIE) return // return if movie - nextEpisode = media.episodes.firstOrNull{ it.number > currentEp.number } - ?: media.episodes.first() +// nextEpisode = media.episodes.firstOrNull{ it.number > currentEp.number } +// ?: media.episodes.first() + + nextEpisodeId = media2.playlist.firstOrNull { it.number > media2.getEpisodeById(episodeId).number }?.mediaId + ?: media2.playlist.first().mediaId } // remove unneeded info from the media title before searching diff --git a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt index 449919d..909e766 100644 --- a/app/src/main/java/org/mosad/teapod/util/DataTypes.kt +++ b/app/src/main/java/org/mosad/teapod/util/DataTypes.kt @@ -44,6 +44,78 @@ data class ItemMedia( /** * TODO the episodes workflow could use a clean up/rework */ +// TODO replace playlist: List with a map? +data class AoDMedia( + val aodId: Int, + val type: DataTypes.MediaType, + val title: String, + val shortText: String, + val posterURL: String, + var year: Int, + var age: Int, + val similar: List, + val playlist: List, +) { + fun hasEpisode(mediaId: Int) = playlist.any { it.mediaId == mediaId } + fun getEpisodeById(mediaId: Int) = playlist.firstOrNull { it.mediaId == mediaId } + ?: AoDEpisodeNone +} + +data class AoDEpisode( + val mediaId: Int, + val title: String, + val description: String, + val shortDesc: String, + val imageURL: String, + val number: Int, + var watched: Boolean, + val watchedCallback: String, + val streams: MutableList, +){ + fun hasDub() = streams.any { it.language == Locale.GERMAN } + + /** + * get the preferred stream + * @return the preferred stream, if not present use the first stream + */ + fun getPreferredStream(language: Locale) = streams.firstOrNull { it.language == language } + ?: streams.first() +} + +// TODO will be watched info (state and callback) -> remove description and number +data class AoDEpisodeInfo( + val aodMediaId: Int, + val shortDesc: String, + var watched: Boolean, + val watchedCallback: String, +) + +val AoDMediaNone = AoDMedia( + -1, + DataTypes.MediaType.OTHER, + "", + "", + "", + -1, + -1, + listOf(), + listOf() +) + +val AoDEpisodeNone = AoDEpisode( + -1, + "", + "", + "", + "", + -1, + false, + "", + mutableListOf() +) + +// LEGACY + data class Media( val id: Int, val link: String, diff --git a/app/src/main/java/org/mosad/teapod/util/adapter/EpisodeItemAdapter.kt b/app/src/main/java/org/mosad/teapod/util/adapter/EpisodeItemAdapter.kt index 89b0bf5..62416d9 100644 --- a/app/src/main/java/org/mosad/teapod/util/adapter/EpisodeItemAdapter.kt +++ b/app/src/main/java/org/mosad/teapod/util/adapter/EpisodeItemAdapter.kt @@ -11,10 +11,10 @@ import com.bumptech.glide.request.RequestOptions import jp.wasabeef.glide.transformations.RoundedCornersTransformation import org.mosad.teapod.R import org.mosad.teapod.databinding.ItemEpisodeBinding -import org.mosad.teapod.util.Episode +import org.mosad.teapod.util.AoDEpisode import org.mosad.teapod.util.tmdb.TMDBTVEpisode -class EpisodeItemAdapter(private val episodes: List, private val tmdbEpisodes: List?) : RecyclerView.Adapter() { +class EpisodeItemAdapter(private val episodes: List, private val tmdbEpisodes: List?) : RecyclerView.Adapter() { var onImageClick: ((String, Int) -> Unit)? = null @@ -41,8 +41,8 @@ class EpisodeItemAdapter(private val episodes: List, private val tmdbEp "" } - if (episodes[position].posterUrl.isNotEmpty()) { - Glide.with(context).load(ep.posterUrl) + if (ep.imageURL.isNotEmpty()) { + Glide.with(context).load(ep.imageURL) .apply(RequestOptions.placeholderOf(ColorDrawable(Color.DKGRAY))) .apply(RequestOptions.bitmapTransform(RoundedCornersTransformation(10, 0))) .into(holder.binding.imageEpisode) diff --git a/fastlane/metadata/android/de/full_description.txt b/fastlane/metadata/android/de/full_description.txt index 81eee9c..43da35b 100644 --- a/fastlane/metadata/android/de/full_description.txt +++ b/fastlane/metadata/android/de/full_description.txt @@ -1,6 +1,6 @@ Teapod ist eine inoffizielle App für Anime-on-Demand (AoD). -* Schau dir alle Title von AoD auf deinem Android Gerät an +* Schau dir alle Titel von AoD auf deinem Android Gerät an * Nativer Player auf Basis des ExoPayers * Bevorzuge die OmU Version über die App-Einstellungen * Speicher deine lieblings Anime in "Meine Liste"