Browse Source

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
pull/49/head
Jannik 4 months ago
parent
commit
0797e9fa3d
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
  1. 3
      app/build.gradle
  2. 26
      app/src/main/java/org/mosad/teapod/parser/crunchyroll/DataTypes.kt
  3. 22
      app/src/main/java/org/mosad/teapod/preferences/Preferences.kt
  4. 6
      app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt
  5. 2
      app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AccountFragment.kt
  6. 3
      app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt
  7. 39
      app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt
  8. 7
      app/src/main/java/org/mosad/teapod/util/tmdb/TMDBApiController.kt
  9. 6
      app/src/main/res/layout/fragment_account.xml
  10. 4
      app/src/main/res/values-de-rDE/strings.xml
  11. 7
      app/src/main/res/values/strings.xml

3
app/build.gradle

@ -59,14 +59,13 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'com.google.code.gson:gson:2.8.8'
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'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.15.0'
implementation 'com.google.android.exoplayer:extension-mediasession:2.15.0'
implementation 'org.jsoup:jsoup:1.14.2'
implementation 'com.github.bumptech.glide:glide:4.12.0'
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.afollestad.material-dialogs:core:3.3.0'

26
app/src/main/java/org/mosad/teapod/parser/crunchyroll/DataTypes.kt

@ -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)
/**

22
app/src/main/java/org/mosad/teapod/preferences/Preferences.kt

@ -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,22 +26,22 @@ object Preferences {
)
}
fun savePreferSecondary(context: Context, preferSecondary: Boolean) {
fun savePreferredLocal(context: Context, preferredLocale: Locale) {
with(getSharedPref(context).edit()) {
putBoolean(context.getString(R.string.save_key_prefer_secondary), preferSecondary)
putString(context.getString(R.string.save_key_preferred_local), preferredLocale.toLanguageTag())
apply()
}
this.preferSecondary = preferSecondary
this.preferredLocale = preferredLocale
}
fun savePreferredLocal(context: Context, preferredLocale: Locale) {
fun savePreferSecondary(context: Context, preferSubbed: Boolean) {
with(getSharedPref(context).edit()) {
putString(context.getString(R.string.save_key_preferred_local), preferredLocale.toLanguageTag())
putBoolean(context.getString(R.string.save_key_prefer_secondary), preferSubbed)
apply()
}
this.preferredLocale = preferredLocale
this.preferSubbed = preferSubbed
}
fun saveAutoplay(context: Context, autoplay: Boolean) {
@ -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
)

6
app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AboutFragment.kt

@ -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),

2
app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/AccountFragment.kt

@ -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)

3
app/src/main/java/org/mosad/teapod/ui/activity/main/fragments/MediaFragment.kt

@ -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

39
app/src/main/java/org/mosad/teapod/ui/activity/player/PlayerViewModel.kt

@ -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.

7
app/src/main/java/org/mosad/teapod/util/tmdb/TMDBApiController.kt

@ -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) {

6
app/src/main/res/layout/fragment_account.xml

@ -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>

4
app/src/main/res/values-de-rDE/strings.xml

@ -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>

7
app/src/main/res/values/strings.xml

@ -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>

Loading…
Cancel
Save

Du besuchst diese Seite mit einem veralteten IPv4-Internetzugang. Möglicherweise treten in Zukunft Probleme mit der Erreichbarkeit und Performance auf. Bitte frage deinen Internetanbieter oder Netzwerkadministrator nach IPv6-Unterstützung.
You are visiting this site with an outdated IPv4 internet access. You may experience problems with accessibility and performance in the future. Please ask your ISP or network administrator for IPv6 support.
Weitere Infos | More Information
Klicke zum schließen | Click to close