Fix multiple language related issues
* fix playback for other shows with no language set in cr API * fix selection of preferred season for languages other than german * add support for all content languages to TMDBApiController * preferSecondary is now preferSubbed, this describes the function more clearly * remove jsoup, not used anymore
This commit is contained in:
		| @ -224,22 +224,13 @@ data class Seasons( | ||||
|     @SerialName("items") val items: List<Season> | ||||
| ) { | ||||
|     fun getPreferredSeason(local: Locale): Season { | ||||
|         // try to get the the first seasons which matches the preferred local | ||||
|         items.forEach { season -> | ||||
|             if (season.title.startsWith("(${local.language})", true)) { | ||||
|                 return season | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // if there is no season with the preferred local, try to find a subbed season | ||||
|         items.forEach { season -> | ||||
|             if (season.isSubbed) { | ||||
|                 return season | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // if there is no preferred language season and no sub, use the first season | ||||
|         return items.first() | ||||
|         return items.firstOrNull { season -> | ||||
|             // try to get the the first seasons which matches the preferred local | ||||
|             season.slugTitle.endsWith("${local.displayLanguage}-dub", true) | ||||
|         } ?: items.firstOrNull { season -> | ||||
|             // if there is no season with the preferred local, try to find a subbed season | ||||
|             season.isSubbed | ||||
|         } ?: items.first() // if no preferred language and no sub, use the first season | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -247,6 +238,7 @@ data class Seasons( | ||||
| data class Season( | ||||
|     @SerialName("id") val id: String, | ||||
|     @SerialName("title") val title: String, | ||||
|     @SerialName("slug_title") val slugTitle: String, | ||||
|     @SerialName("series_id") val seriesId: String, | ||||
|     @SerialName("season_number") val seasonNumber: Int, | ||||
|     @SerialName("is_subbed") val isSubbed: Boolean, | ||||
| @ -254,7 +246,7 @@ data class Season( | ||||
| ) | ||||
|  | ||||
| val NoneSeasons = Seasons(0, emptyList()) | ||||
| val NoneSeason = Season("", "", "", 0, isSubbed = false, isDubbed = false) | ||||
| val NoneSeason = Season("", "", "", "", 0, isSubbed = false, isDubbed = false) | ||||
|  | ||||
|  | ||||
| /** | ||||
|  | ||||
| @ -8,10 +8,10 @@ import java.util.* | ||||
|  | ||||
| object Preferences { | ||||
|  | ||||
|     var preferSecondary = false | ||||
|         internal set | ||||
|     var preferredLocale: Locale = Locale.forLanguageTag("en-US") // TODO this should be saved (potential offline usage) but fetched on start | ||||
|         internal set | ||||
|     var preferSubbed = false | ||||
|         internal set | ||||
|     var autoplay = true | ||||
|         internal set | ||||
|     var devSettings = false | ||||
| @ -26,15 +26,6 @@ object Preferences { | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     fun savePreferSecondary(context: Context, preferSecondary: Boolean) { | ||||
|         with(getSharedPref(context).edit()) { | ||||
|             putBoolean(context.getString(R.string.save_key_prefer_secondary), preferSecondary) | ||||
|             apply() | ||||
|         } | ||||
|  | ||||
|         this.preferSecondary = preferSecondary | ||||
|     } | ||||
|  | ||||
|     fun savePreferredLocal(context: Context, preferredLocale: Locale) { | ||||
|         with(getSharedPref(context).edit()) { | ||||
|             putString(context.getString(R.string.save_key_preferred_local), preferredLocale.toLanguageTag()) | ||||
| @ -44,6 +35,15 @@ object Preferences { | ||||
|         this.preferredLocale = preferredLocale | ||||
|     } | ||||
|  | ||||
|     fun savePreferSecondary(context: Context, preferSubbed: Boolean) { | ||||
|         with(getSharedPref(context).edit()) { | ||||
|             putBoolean(context.getString(R.string.save_key_prefer_secondary), preferSubbed) | ||||
|             apply() | ||||
|         } | ||||
|  | ||||
|         this.preferSubbed = preferSubbed | ||||
|     } | ||||
|  | ||||
|     fun saveAutoplay(context: Context, autoplay: Boolean) { | ||||
|         with(getSharedPref(context).edit()) { | ||||
|             putBoolean(context.getString(R.string.save_key_autoplay), autoplay) | ||||
| @ -77,14 +77,14 @@ object Preferences { | ||||
|     fun load(context: Context) { | ||||
|         val sharedPref = getSharedPref(context) | ||||
|  | ||||
|         preferSecondary = sharedPref.getBoolean( | ||||
|             context.getString(R.string.save_key_prefer_secondary), false | ||||
|         ) | ||||
|         preferredLocale = Locale.forLanguageTag( | ||||
|             sharedPref.getString( | ||||
|                 context.getString(R.string.save_key_preferred_local), "en-US" | ||||
|             ) ?: "en-US" | ||||
|         ) | ||||
|         preferSubbed = sharedPref.getBoolean( | ||||
|             context.getString(R.string.save_key_prefer_secondary), false | ||||
|         ) | ||||
|         autoplay = sharedPref.getBoolean( | ||||
|             context.getString(R.string.save_key_autoplay), true | ||||
|         ) | ||||
|  | ||||
| @ -113,9 +113,9 @@ class AboutFragment : Fragment() { | ||||
|                 "https://github.com/google/material-design-icons", License.APACHE2), | ||||
|             ThirdPartyComponent("Material Dialogs", "", "Aidan Follestad", | ||||
|                 "https://github.com/afollestad/material-dialogs", License.APACHE2), | ||||
|             ThirdPartyComponent("Jsoup", "2009 - 2020", "Jonathan Hedley", | ||||
|                 "https://jsoup.org/", License.MIT), | ||||
|             ThirdPartyComponent("kotlinx.coroutines", "2016 - 2019", "JetBrains", | ||||
|             ThirdPartyComponent("Ktor", "2014-2021", "JetBrains s.r.o and contributors", | ||||
|                 "https://ktor.io/", License.APACHE2), | ||||
|             ThirdPartyComponent("kotlinx.coroutines", "2016-2021", "JetBrains s.r.o", | ||||
|                 "https://github.com/Kotlin/kotlinx.coroutines", License.APACHE2), | ||||
|             ThirdPartyComponent("Glide", "2014", "Google Inc.", | ||||
|                 "https://github.com/bumptech/glide", License.BSD2), | ||||
|  | ||||
| @ -85,7 +85,7 @@ class AccountFragment : Fragment() { | ||||
|                 profile.await().preferredContentSubtitleLanguage | ||||
|             ).displayLanguage | ||||
|         } | ||||
|         binding.switchSecondary.isChecked = Preferences.preferSecondary | ||||
|         binding.switchSecondary.isChecked = Preferences.preferSubbed | ||||
|         binding.switchAutoplay.isChecked = Preferences.autoplay | ||||
|         binding.textThemeSelected.text = when (Preferences.theme) { | ||||
|             Theme.DARK -> getString(R.string.theme_dark) | ||||
|  | ||||
| @ -51,9 +51,6 @@ class MediaFragment(private val mediaIdStr: String) : Fragment() { | ||||
|  | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
|  | ||||
|         println("onViewCreated") | ||||
|  | ||||
|         binding.frameLoading.visibility = View.VISIBLE | ||||
|  | ||||
|         // tab layout and pager | ||||
|  | ||||
| @ -47,8 +47,6 @@ 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.Meta | ||||
| import org.mosad.teapod.util.TVShowMeta | ||||
| import org.mosad.teapod.util.tmdb.TMDBTVSeason | ||||
| import java.util.* | ||||
|  | ||||
| @ -64,12 +62,12 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) | ||||
|     private val mediaSession = MediaSessionCompat(application, "TEAPOD_PLAYER_SESSION") | ||||
|  | ||||
|     val currentEpisodeChangedListener = ArrayList<() -> Unit>() | ||||
|     private val preferredLanguage = if (Preferences.preferSecondary) Locale.JAPANESE else Locale.GERMAN | ||||
|     private var currentPlayhead: Long = 0 | ||||
|  | ||||
|     // tmdb/meta data TODO currently not implemented for cr | ||||
|     var mediaMeta: Meta? = null | ||||
|         internal set | ||||
|     // tmdb/meta data | ||||
|     // TODO meta data currently not implemented for cr | ||||
| //    var mediaMeta: Meta? = null | ||||
| //        internal set | ||||
|     var tmdbTVSeason: TMDBTVSeason? =null | ||||
|         internal set | ||||
|     var currentEpisodeMeta: EpisodeMeta? = null | ||||
| @ -224,8 +222,9 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) | ||||
|                 currentPlayback.streams.adaptive_hls[fallbackLocal.toLanguageTag()]?.url | ||||
|             } | ||||
|             else -> { | ||||
|                 // if no language tag is present use the first entry | ||||
|                 currentLanguage = Locale.ROOT | ||||
|                 currentPlayback.streams.adaptive_hls[Locale.ROOT.toLanguageTag()]?.url ?: "" | ||||
|                 currentPlayback.streams.adaptive_hls.entries.first().value.url | ||||
|             } | ||||
|         } | ||||
|         println("stream url: $url") | ||||
| @ -267,25 +266,25 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application) | ||||
|         return episodes.items.lastOrNull()?.id == currentEpisode.id | ||||
|     } | ||||
|  | ||||
|     fun getEpisodeMetaByAoDMediaId(aodMediaId: Int): EpisodeMeta? { | ||||
|         val meta = mediaMeta | ||||
|         return if (meta is TVShowMeta) { | ||||
|             meta.episodes.firstOrNull { it.aodMediaId == aodMediaId } | ||||
|         } else { | ||||
|             null | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // TODO reimplement for cr | ||||
|     private suspend fun loadMediaMeta(aodId: Int): Meta? { | ||||
| //    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 | ||||
|     } | ||||
| // | ||||
| //        return null | ||||
| //    } | ||||
|  | ||||
|     /** | ||||
|      * Update the playhead of the current episode, if currentPosition > 1000ms. | ||||
|  | ||||
| @ -34,6 +34,7 @@ import kotlinx.coroutines.coroutineScope | ||||
| import kotlinx.coroutines.invoke | ||||
| import kotlinx.serialization.SerializationException | ||||
| import kotlinx.serialization.json.Json | ||||
| import org.mosad.teapod.preferences.Preferences | ||||
| import org.mosad.teapod.util.concatenate | ||||
|  | ||||
| /** | ||||
| @ -54,7 +55,6 @@ class TMDBApiController { | ||||
|  | ||||
|     private val apiUrl = "https://api.themoviedb.org/3" | ||||
|     private val apiKey = "de959cf9c07a08b5ca7cb51cda9a40c2" | ||||
|     private val language = "de" | ||||
|  | ||||
|     companion object{ | ||||
|         const val imageUrl = "https://image.tmdb.org/t/p/w500" | ||||
| @ -65,7 +65,10 @@ class TMDBApiController { | ||||
|         parameters: List<Pair<String, Any?>> = emptyList() | ||||
|     ): T = coroutineScope { | ||||
|         val path = "$apiUrl$endpoint" | ||||
|         val params = concatenate(listOf("api_key" to apiKey, "language" to language), parameters) | ||||
|         val params = concatenate( | ||||
|             listOf("api_key" to apiKey, "language" to Preferences.preferredLocale.language), | ||||
|             parameters | ||||
|         ) | ||||
|  | ||||
|         // TODO handle FileNotFoundException | ||||
|         return@coroutineScope (Dispatchers.IO) { | ||||
|  | ||||
| @ -198,7 +198,7 @@ | ||||
|                         android:id="@+id/imageView3" | ||||
|                         android:layout_width="wrap_content" | ||||
|                         android:layout_height="wrap_content" | ||||
|                         android:contentDescription="@string/settings_secondary" | ||||
|                         android:contentDescription="@string/settings_prefer_subbed" | ||||
|                         android:minWidth="48dp" | ||||
|                         android:minHeight="48dp" | ||||
|                         android:padding="9dp" | ||||
| @ -225,7 +225,7 @@ | ||||
|                                 android:layout_width="match_parent" | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_weight="1" | ||||
|                                 android:text="@string/settings_secondary" | ||||
|                                 android:text="@string/settings_prefer_subbed" | ||||
|                                 android:textSize="16sp" /> | ||||
|  | ||||
|                             <TextView | ||||
| @ -234,7 +234,7 @@ | ||||
|                                 android:layout_height="wrap_content" | ||||
|                                 android:layout_weight="1" | ||||
|                                 android:maxLines="2" | ||||
|                                 android:text="@string/settings_secondary_desc" | ||||
|                                 android:text="@string/settings_prefer_subbed_desc" | ||||
|                                 android:textColor="?textSecondary" /> | ||||
|                         </LinearLayout> | ||||
|  | ||||
|  | ||||
| @ -42,8 +42,8 @@ | ||||
|     <string name="settings_content_language">Bevorzuge Inhaltssprache</string> | ||||
|     <string name="settings_content_language_desc">Englisch</string> | ||||
|     <string name="settings_content_language_none">Keine</string> | ||||
|     <string name="settings_secondary">Bevorzuge Japanisch (OmU)</string> | ||||
|     <string name="settings_secondary_desc">Japanisch verwenden, sofern vorhanden</string> | ||||
|     <string name="settings_prefer_subbed">Bevorzuge OmU</string> | ||||
|     <string name="settings_prefer_subbed_desc">Original Sprache verwenden, sofern vorhanden</string> | ||||
|     <string name="settings_autoplay">Autoplay</string> | ||||
|     <string name="settings_autoplay_desc">Nächste Episode automatisch abspielen</string> | ||||
|     <string name="theme">Design</string> | ||||
|  | ||||
| @ -40,7 +40,7 @@ | ||||
|     <string name="component_poster_desc" translatable="false">episode poster</string> | ||||
|     <string name="component_watched_desc" translatable="false">already watched</string> | ||||
|  | ||||
|     <!-- settings fragment --> | ||||
|     <!-- account fragment --> | ||||
|     <string name="account">Account</string> | ||||
|     <string name="account_login_ex" translatable="false">user@example.com</string> | ||||
|     <string name="account_login_desc">Tap to edit</string> | ||||
| @ -50,8 +50,8 @@ | ||||
|     <string name="settings_content_language">Preferred content language</string> | ||||
|     <string name="settings_content_language_desc">English</string> | ||||
|     <string name="settings_content_language_none">None</string> | ||||
|     <string name="settings_secondary">Prefer japanese (sub)</string> | ||||
|     <string name="settings_secondary_desc">Use japanese, if present</string> | ||||
|     <string name="settings_prefer_subbed">Prefer subbed</string> | ||||
|     <string name="settings_prefer_subbed_desc">Use original language, if present</string> | ||||
|     <string name="settings_autoplay">Autoplay</string> | ||||
|     <string name="settings_autoplay_desc">Play next episode automatically</string> | ||||
|     <string name="theme">Theme</string> | ||||
| @ -131,6 +131,7 @@ | ||||
|     <string name="preference_file_key" translatable="false">org.mosad.teapod.preferences</string> | ||||
|     <string name="save_key_user_login" translatable="false">org.mosad.teapod.user_login</string> | ||||
|     <string name="save_key_user_password" translatable="false">org.mosad.teapod.user_password</string> | ||||
|     <!-- for legacy reasons the prefer subbed key is called prefer_secondary--> | ||||
|     <string name="save_key_prefer_secondary" translatable="false">org.mosad.teapod.prefer_secondary</string> | ||||
|     <string name="save_key_preferred_local" translatable="false">org.mosad.teapod.preferred_local</string> | ||||
|     <string name="save_key_autoplay" translatable="false">org.mosad.teapod.autoplay</string> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user