From 7fbf639a70cc3e28ca121a5c7df03fc68a706a9b Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 20 Mar 2022 14:29:32 +0100 Subject: [PATCH 1/2] add metadb support for crunchyroll also remove gson snice it's unused now --- app/build.gradle | 1 - app/proguard-rules.pro | 4 - .../teapod/ui/activity/main/MainActivity.kt | 16 +- .../activity/main/fragments/AboutFragment.kt | 2 - .../main/viewmodel/MediaFragmentViewModel.kt | 4 +- .../ui/activity/player/PlayerActivity.kt | 1 - .../ui/activity/player/PlayerViewModel.kt | 69 +++----- .../ui/components/EpisodesListPlayer.kt | 2 +- .../org/mosad/teapod/util/MetaDBController.kt | 159 ------------------ .../util/adapter/PlayerEpisodeItemAdapter.kt | 4 +- .../org/mosad/teapod/util/metadb/DatTypes.kt | 57 +++++++ .../teapod/util/metadb/MetaDBController.kt | 88 ++++++++++ 12 files changed, 189 insertions(+), 218 deletions(-) delete mode 100644 app/src/main/java/org/mosad/teapod/util/MetaDBController.kt create mode 100644 app/src/main/java/org/mosad/teapod/util/metadb/DatTypes.kt create mode 100644 app/src/main/java/org/mosad/teapod/util/metadb/MetaDBController.kt diff --git a/app/build.gradle b/app/build.gradle index 924ba20..d5c6216 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,7 +60,6 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' implementation 'com.google.android.material:material:1.5.0' - implementation 'com.google.code.gson:gson:2.8.8' // TODO remove, still used by metadb implementation 'com.google.android.exoplayer:exoplayer-core:2.15.0' implementation 'com.google.android.exoplayer:exoplayer-hls:2.15.0' implementation 'com.google.android.exoplayer:exoplayer-dash:2.15.0' diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 641efbc..73bba8f 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -24,10 +24,6 @@ -keep class org.json.** { *; } -#Gson --keepattributes Signature --dontwarn sun.misc.** - # kotlinx.serialization # Keep `Companion` object fields of serializable classes. # This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects. diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt index 638ea87..9c4e09c 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/MainActivity.kt @@ -45,6 +45,7 @@ import org.mosad.teapod.ui.activity.onboarding.OnboardingActivity import org.mosad.teapod.ui.activity.player.PlayerActivity import org.mosad.teapod.ui.components.LoginDialog import org.mosad.teapod.util.DataTypes +import org.mosad.teapod.util.metadb.MetaDBController import java.util.* import kotlin.system.measureTimeMillis @@ -141,6 +142,9 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen Preferences.load(this) EncryptedPreferences.readCredentials(this) + // load meta db at the start, it doesn't depend on any third party + val metaJob = initMetaDB() + // always initialize the api token Crunchyroll.initBasicApiToken() @@ -152,14 +156,17 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen ) { showOnboarding() } else { - runBlocking { initCrunchyroll().joinAll() } + runBlocking { + initCrunchyroll().joinAll() + metaJob.join() // meta loading should be done here + } } } Log.i(classTag, "loading in $time ms") } private fun initCrunchyroll(): List { - val scope = CoroutineScope(Dispatchers.IO + CoroutineName("InitialLoadingScope")) + val scope = CoroutineScope(Dispatchers.IO + CoroutineName("InitialCrunchyLoading")) return listOf( scope.launch { Crunchyroll.index() }, scope.launch { Crunchyroll.account() }, @@ -172,6 +179,11 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen ) } + private fun initMetaDB(): Job { + val scope = CoroutineScope(Dispatchers.IO + CoroutineName("InitialMetaDBLoading")) + return scope.launch { MetaDBController.list() } + } + private fun showLoginDialog() { LoginDialog(this, false).positiveButton { EncryptedPreferences.saveCredentials(login, password, context) diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt index 31ff0c3..6cd1fa9 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt @@ -107,8 +107,6 @@ class AboutFragment : Fragment() { "https://github.com/material-components/material-components-android", License.APACHE2), ThirdPartyComponent("ExoPlayer", "2014 - 2020", "The Android Open Source Project", "https://github.com/google/ExoPlayer", License.APACHE2), - ThirdPartyComponent("Gson", "2008", "Google Inc.", - "https://github.com/google/gson", License.APACHE2), ThirdPartyComponent("Material design icons", "2020", "Google Inc.", "https://github.com/google/material-design-icons", License.APACHE2), ThirdPartyComponent("Material Dialogs", "", "Aidan Follestad", 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 2e4a260..b7a0cde 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 @@ -8,7 +8,7 @@ import kotlinx.coroutines.launch import org.mosad.teapod.parser.crunchyroll.* import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.util.DataTypes.MediaType -import org.mosad.teapod.util.Meta +import org.mosad.teapod.util.metadb.Meta import org.mosad.teapod.util.tmdb.* /** @@ -59,7 +59,7 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic ).joinAll() // println("series: $seriesCrunchy") // println("seasons: $seasonsCrunchy") - println(upNextSeries) +// println(upNextSeries) // load the preferred season (preferred language, language per season, not per stream) currentSeasonCrunchy = seasonsCrunchy.getPreferredSeason(Preferences.preferredLocale) diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt index a48969b..a2df0ac 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerActivity.kt @@ -425,7 +425,6 @@ class PlayerActivity : AppCompatActivity() { val seekTime = (it.openingStart + it.openingDuration) - model.player.currentPosition model.seekToOffset(seekTime) } - } /** diff --git a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt index 9553211..3e54040 100644 --- a/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt +++ b/app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt @@ -46,8 +46,10 @@ import org.mosad.teapod.parser.crunchyroll.NoneEpisode import org.mosad.teapod.parser.crunchyroll.NoneEpisodes import org.mosad.teapod.parser.crunchyroll.NonePlayback import org.mosad.teapod.preferences.Preferences -import org.mosad.teapod.util.EpisodeMeta -import org.mosad.teapod.util.tmdb.TMDBTVSeason +import org.mosad.teapod.util.metadb.EpisodeMeta +import org.mosad.teapod.util.metadb.Meta +import org.mosad.teapod.util.metadb.MetaDBController +import org.mosad.teapod.util.metadb.TVShowMeta import java.util.* /** @@ -56,6 +58,7 @@ import java.util.* * the next episode will be update and the callback is handled. */ class PlayerViewModel(application: Application) : AndroidViewModel(application) { + private val classTag = javaClass.name val player = SimpleExoPlayer.Builder(application).build() private val dataSourceFactory = DefaultDataSourceFactory(application, Util.getUserAgent(application, "Teapod")) @@ -65,13 +68,12 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) private var currentPlayhead: Long = 0 // tmdb/meta data - // TODO meta data currently not implemented for cr -// var mediaMeta: Meta? = null -// internal set - var tmdbTVSeason: TMDBTVSeason? =null + var mediaMeta: Meta? = null internal set var currentEpisodeMeta: EpisodeMeta? = null internal set +// var tmdbTVSeason: TMDBTVSeason? =null +// internal set // crunchyroll episodes/playback var episodes = NoneEpisodes @@ -108,7 +110,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) mediaSession.release() player.release() - Log.d(javaClass.name, "Released player") + Log.d(classTag, "Released player") } /** @@ -124,22 +126,12 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) fun loadMediaAsync(seasonId: String, episodeId: String) = viewModelScope.launch { episodes = Crunchyroll.episodes(seasonId) + mediaMeta = loadMediaMeta(episodes.items.first().seriesId) + + Log.d(classTag, "meta: $mediaMeta") setCurrentEpisode(episodeId) playCurrentMedia(currentPlayhead) - - // TODO reimplement for cr - // run async as it should be loaded by the time the episodes a -// viewModelScope.launch { -// // get tmdb season info, if metaDB knows the tv show -// if (media.type == DataTypes.MediaType.TVSHOW && mediaMeta != null) { -// val tvShowMeta = mediaMeta as TVShowMeta -// tmdbTVSeason = TMDBApiController().getTVSeasonDetails(tvShowMeta.tmdbId, tvShowMeta.tmdbSeasonNumber) -// } -// } -// -// currentEpisodeMeta = getEpisodeMetaByAoDMediaId(currentEpisodeAoD.mediaId) -// currentLanguage = currentEpisodeAoD.getPreferredStream(preferredLanguage).language } fun setLanguage(language: Locale) { @@ -174,6 +166,15 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) episode.id == episodeId } ?: NoneEpisode + // update current episode meta + currentEpisodeMeta = if (mediaMeta is TVShowMeta && currentEpisode.episodeNumber != null) { + (mediaMeta as TVShowMeta) + .seasons[currentEpisode.seasonNumber - 1] + .episodes[currentEpisode.episodeNumber!! - 1] + } else { + null + } + // update player gui (title, next ep button) after currentEpisode has changed currentEpisodeChangedListener.forEach { it() } @@ -195,9 +196,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) } ) } - println("loaded playback ${currentEpisode.playback}") - - // TODO update metadata and language (it should not be needed to update the language here!) + Log.i(classTag, "playback: ${currentEpisode.playback}") if (startPlayback) { playCurrentMedia() @@ -227,7 +226,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) currentPlayback.streams.adaptive_hls.entries.first().value.url } } - println("stream url: $url") + Log.d(classTag, "stream url: $url") // create the media source object val mediaSource = HlsMediaSource.Factory(dataSourceFactory).createMediaSource( @@ -266,25 +265,9 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) return episodes.items.lastOrNull()?.id == currentEpisode.id } - // TODO reimplement for cr -// fun getEpisodeMetaByAoDMediaId(aodMediaId: Int): EpisodeMeta? { -// val meta = mediaMeta -// return if (meta is TVShowMeta) { -// meta.episodes.firstOrNull { it.aodMediaId == aodMediaId } -// } else { -// null -// } -// } -// -// private suspend fun loadMediaMeta(aodId: Int): Meta? { -// return if (media.type == DataTypes.MediaType.TVSHOW) { -// MetaDBController().getTVShowMetadata(aodId) -// } else { -// null -// } -// -// return null -// } + private suspend fun loadMediaMeta(crSeriesId: String): Meta? { + return MetaDBController.getTVShowMetadata(crSeriesId) + } /** * Update the playhead of the current episode, if currentPosition > 1000ms. diff --git a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt index ce182f2..a29af19 100644 --- a/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt +++ b/app/src/main/java/org/mosad/teapod/ui/components/EpisodesListPlayer.kt @@ -28,7 +28,7 @@ class EpisodesListPlayer @JvmOverloads constructor( } model?.let { - adapterRecEpisodes = PlayerEpisodeItemAdapter(model.episodes, model.tmdbTVSeason?.episodes) + adapterRecEpisodes = PlayerEpisodeItemAdapter(model.episodes) adapterRecEpisodes.onImageClick = {_, episodeId -> (this.parent as ViewGroup).removeView(this) model.setCurrentEpisode(episodeId, startPlayback = true) diff --git a/app/src/main/java/org/mosad/teapod/util/MetaDBController.kt b/app/src/main/java/org/mosad/teapod/util/MetaDBController.kt deleted file mode 100644 index 2ffb770..0000000 --- a/app/src/main/java/org/mosad/teapod/util/MetaDBController.kt +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Teapod - * - * Copyright 2020-2022 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -package org.mosad.teapod.util - -import android.util.Log -import com.google.gson.Gson -import com.google.gson.annotations.SerializedName -import kotlinx.coroutines.* -import java.io.FileNotFoundException -import java.net.URL - -/** - * TODO remove gson usage - */ -class MetaDBController { - - companion object { - private const val repoUrl = "https://gitlab.com/Seil0/teapodmetadb/-/raw/main/aod/" - - var mediaList = MediaList(listOf()) - private var metaCacheList = arrayListOf() - - @Suppress("BlockingMethodInNonBlockingContext") - suspend fun list() = withContext(Dispatchers.IO) { - val url = URL("$repoUrl/list.json") - val json = url.readText() - - mediaList = Gson().fromJson(json, MediaList::class.java) - } - } - - /** - * Get the meta data for a movie from MetaDB - * @param aodId The AoD id of the media - * @return A meta movie object, or null if not found - */ - suspend fun getMovieMetadata(aodId: Int): MovieMeta? { - return metaCacheList.firstOrNull { - it.aodId == aodId - } as MovieMeta? ?: getMovieMetadataFromDB(aodId) - } - - /** - * Get the meta data for a tv show from MetaDB - * @param aodId The AoD id of the media - * @return A meta tv show object, or null if not found - */ - suspend fun getTVShowMetadata(aodId: Int): TVShowMeta? { - return metaCacheList.firstOrNull { - it.aodId == aodId - } as TVShowMeta? ?: getTVShowMetadataFromDB(aodId) - } - - @Suppress("BlockingMethodInNonBlockingContext") - private suspend fun getMovieMetadataFromDB(aodId: Int): MovieMeta? = withContext(Dispatchers.IO) { - val url = URL("$repoUrl/movie/$aodId/media.json") - return@withContext try { - val json = url.readText() - val meta = Gson().fromJson(json, MovieMeta::class.java) - metaCacheList.add(meta) - - meta - } catch (ex: FileNotFoundException) { - Log.w(javaClass.name, "Waring: The requested file was not found. Requested ID: $aodId", ex) - null - } - } - - @Suppress("BlockingMethodInNonBlockingContext") - private suspend fun getTVShowMetadataFromDB(aodId: Int): TVShowMeta? = withContext(Dispatchers.IO) { - val url = URL("$repoUrl/tv/$aodId/media.json") - return@withContext try { - val json = url.readText() - val meta = Gson().fromJson(json, TVShowMeta::class.java) - metaCacheList.add(meta) - - meta - } catch (ex: FileNotFoundException) { - Log.w(javaClass.name, "Waring: The requested file was not found. Requested ID: $aodId", ex) - null - } - } - -} - -// class representing the media list json object -data class MediaList( - val media: List -) - -// abstract class used for meta data objects (tv, movie) -abstract class Meta { - abstract val id: Int - abstract val aodId: Int - abstract val tmdbId: Int -} - -// class representing the movie json object -data class MovieMeta( - override val id: Int, - @SerializedName("aod_id") - override val aodId: Int, - @SerializedName("tmdb_id") - override val tmdbId: Int -): Meta() - -// class representing the tv show json object -data class TVShowMeta( - override val id: Int, - @SerializedName("aod_id") - override val aodId: Int, - @SerializedName("tmdb_id") - override val tmdbId: Int, - @SerializedName("tmdb_season_id") - val tmdbSeasonId: Int, - @SerializedName("tmdb_season_number") - val tmdbSeasonNumber: Int, - @SerializedName("episodes") - val episodes: List -): Meta() - -// class used in TVShowMeta, part of the tv show json object -data class EpisodeMeta( - val id: Int, - @SerializedName("aod_media_id") - val aodMediaId: Int, - @SerializedName("tmdb_id") - val tmdbId: Int, - @SerializedName("tmdb_number") - val tmdbNumber: Int, - @SerializedName("opening_start") - val openingStart: Long, - @SerializedName("opening_duration") - val openingDuration: Long, - @SerializedName("ending_start") - val endingStart: Long, - @SerializedName("ending_duration") - val endingDuration: Long -) diff --git a/app/src/main/java/org/mosad/teapod/util/adapter/PlayerEpisodeItemAdapter.kt b/app/src/main/java/org/mosad/teapod/util/adapter/PlayerEpisodeItemAdapter.kt index 2035898..e7f8d64 100644 --- a/app/src/main/java/org/mosad/teapod/util/adapter/PlayerEpisodeItemAdapter.kt +++ b/app/src/main/java/org/mosad/teapod/util/adapter/PlayerEpisodeItemAdapter.kt @@ -12,7 +12,7 @@ import org.mosad.teapod.databinding.ItemEpisodePlayerBinding import org.mosad.teapod.parser.crunchyroll.Episodes import org.mosad.teapod.util.tmdb.TMDBTVEpisode -class PlayerEpisodeItemAdapter(private val episodes: Episodes, private val tmdbEpisodes: List?) : RecyclerView.Adapter() { +class PlayerEpisodeItemAdapter(private val episodes: Episodes) : RecyclerView.Adapter() { var onImageClick: ((seasonId: String, episodeId: String) -> Unit)? = null var currentSelected: Int = -1 // -1, since position should never be < 0 @@ -39,8 +39,6 @@ class PlayerEpisodeItemAdapter(private val episodes: Episodes, private val tmdbE holder.binding.textEpisodeTitle2.text = titleText holder.binding.textEpisodeDesc2.text = if (ep.description.isNotEmpty()) { ep.description - } else if (tmdbEpisodes != null && position < tmdbEpisodes.size){ - tmdbEpisodes[position].overview } else { "" } diff --git a/app/src/main/java/org/mosad/teapod/util/metadb/DatTypes.kt b/app/src/main/java/org/mosad/teapod/util/metadb/DatTypes.kt new file mode 100644 index 0000000..32272b9 --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/util/metadb/DatTypes.kt @@ -0,0 +1,57 @@ +package org.mosad.teapod.util.metadb + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +// class representing the media list json object +@Serializable +data class MediaList( + @SerialName("media") val media: List +) + +// abstract class used for meta data objects (tv, movie) +abstract class Meta { + abstract val id: Int + abstract val tmdbId: Int + abstract val crSeriesId: String +} + +// class representing the movie json object +@Serializable +data class MovieMeta( + @SerialName("id") override val id: Int, + @SerialName("tmdb_id") override val tmdbId: Int, + @SerialName("cr_series_id") override val crSeriesId: String, +): Meta() + +// class representing the tv show json object +@Serializable +data class TVShowMeta( + @SerialName("id") override val id: Int, + @SerialName("tmdb_id") override val tmdbId: Int, + @SerialName("cr_series_id") override val crSeriesId: String, + @SerialName("seasons") val seasons: List, +): Meta() + +// class used in TVShowMeta, part of the tv show json object +@Serializable +data class SeasonMeta( + @SerialName("id") val id: Int, + @SerialName("tmdb_season_id") val tmdbSeasonId: Int, + @SerialName("tmdb_season_number") val tmdbSeasonNumber: Int, + @SerialName("cr_season_ids") val crSeasonIds: List, + @SerialName("episodes") val episodes: List, +) + +// class used in TVShowMeta, part of the tv show json object +@Serializable +data class EpisodeMeta( + @SerialName("id") val id: Int, + @SerialName("tmdb_episode_id") val tmdbEpisodeId: Int, + @SerialName("tmdb_episode_number") val tmdbEpisodeNumber: Int, + @SerialName("cr_episode_ids") val crEpisodeIds: List, + @SerialName("opening_start") val openingStart: Long, + @SerialName("opening_duration") val openingDuration: Long, + @SerialName("ending_start") val endingStart: Long, + @SerialName("ending_duration") val endingDuration: Long +) \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/util/metadb/MetaDBController.kt b/app/src/main/java/org/mosad/teapod/util/metadb/MetaDBController.kt new file mode 100644 index 0000000..3389ef7 --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/util/metadb/MetaDBController.kt @@ -0,0 +1,88 @@ +/** + * Teapod + * + * Copyright 2020-2022 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +package org.mosad.teapod.util.metadb + +import android.util.Log +import io.ktor.client.* +import io.ktor.client.features.* +import io.ktor.client.features.json.* +import io.ktor.client.features.json.serializer.* +import io.ktor.client.request.* +import io.ktor.http.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json + +object MetaDBController { + private val TAG = javaClass.name + + private const val repoUrl = "https://gitlab.com/Seil0/teapodmetadb/-/raw/main/crunchy/" + + private val client = HttpClient { + install(JsonFeature) { + serializer = KotlinxSerializer(Json) + } + } + + private var mediaList = MediaList(listOf()) + private var metaCacheList = arrayListOf() + + suspend fun list() = withContext(Dispatchers.IO) { + val raw: String = client.get("$repoUrl/list.json") + mediaList = Json.decodeFromString(raw) + } + + /** + * Get the meta data for a movie from MetaDB + * @param crSeriesId The crunchyroll media id + * @return A meta object, or null if not found + */ + suspend fun getTVShowMetadata(crSeriesId: String): TVShowMeta? { + return if (mediaList.media.contains(crSeriesId)) { + metaCacheList.firstOrNull { + it.crSeriesId == crSeriesId + } as TVShowMeta? ?: getTVShowMetadataFromDB(crSeriesId) + } else { + null + } + } + + private suspend fun getTVShowMetadataFromDB(crSeriesId: String): TVShowMeta? = withContext(Dispatchers.IO) { + return@withContext try { + val raw: String = client.get("$repoUrl/tv/$crSeriesId/media.json") + val meta: TVShowMeta = Json.decodeFromString(raw) + metaCacheList.add(meta) + + meta + } catch (ex: ClientRequestException) { + when (ex.response.status) { + HttpStatusCode.NotFound -> Log.w(TAG, "The requested file was not found. Series ID: $crSeriesId", ex) + else -> Log.e(TAG, "Error while requesting meta data. Series ID: $crSeriesId", ex) + } + + null // todo return none object + } + } + +} From e76cbda04d5437a8ce6c4b9e9f0578beeabdb4e3 Mon Sep 17 00:00:00 2001 From: Jannik Date: Tue, 29 Mar 2022 23:23:10 +0200 Subject: [PATCH 2/2] fix Onboarding not working; fix deprecation in Activity.hideBars() --- app/src/main/AndroidManifest.xml | 5 +++-- app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b801924..448408e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,11 +11,12 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.App.Starting"> + android:theme="@style/AppTheme.Dark"> + android:screenOrientation="portrait" + android:theme="@style/Theme.App.Starting"> diff --git a/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt b/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt index 283d2e7..65c48cd 100644 --- a/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt +++ b/app/src/main/java/org/mosad/teapod/util/ActivityUtils.kt @@ -36,7 +36,12 @@ fun Activity.hideBars() { setDecorFitsSystemWindows(false) insetsController?.apply { hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) - systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE + systemBarsBehavior = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + WindowInsetsController.BEHAVIOR_DEFAULT + } else { + @Suppress("deprecation") + WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE + } } } else { @Suppress("deprecation")