migrate player language settings to DialogFragment; update hideBars()
* player language settings is now aDialogFragment * update hideBars() to work with any window & view combination * update hideBars() to use WindowCompat
This commit is contained in:
parent
c6a00ea061
commit
35157b78f5
|
@ -53,9 +53,11 @@ import kotlinx.coroutines.launch
|
||||||
import org.mosad.teapod.R
|
import org.mosad.teapod.R
|
||||||
import org.mosad.teapod.parser.crunchyroll.NoneEpisode
|
import org.mosad.teapod.parser.crunchyroll.NoneEpisode
|
||||||
import org.mosad.teapod.preferences.Preferences
|
import org.mosad.teapod.preferences.Preferences
|
||||||
|
import org.mosad.teapod.ui.activity.player.fragment.LanguageSettingsDialogFragment
|
||||||
import org.mosad.teapod.ui.components.EpisodesListPlayer
|
import org.mosad.teapod.ui.components.EpisodesListPlayer
|
||||||
import org.mosad.teapod.ui.components.LanguageSettingsPlayer
|
import org.mosad.teapod.util.hideBars
|
||||||
import org.mosad.teapod.util.*
|
import org.mosad.teapod.util.isInPiPMode
|
||||||
|
import org.mosad.teapod.util.navToLauncherTask
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.concurrent.scheduleAtFixedRate
|
import kotlin.concurrent.scheduleAtFixedRate
|
||||||
|
@ -486,11 +488,8 @@ class PlayerActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showLanguageSettings() {
|
private fun showLanguageSettings() {
|
||||||
val languageSettings = LanguageSettingsPlayer(this, model = model).apply {
|
|
||||||
onViewRemovedAction = { model.player.play() }
|
|
||||||
}
|
|
||||||
player_layout.addView(languageSettings)
|
|
||||||
pauseAndHideControls()
|
pauseAndHideControls()
|
||||||
|
LanguageSettingsDialogFragment().show(supportFragmentManager, LanguageSettingsDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,54 +1,75 @@
|
||||||
package org.mosad.teapod.ui.components
|
package org.mosad.teapod.ui.activity.player.fragment
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.DialogInterface
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.util.AttributeSet
|
import android.os.Bundle
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import org.mosad.teapod.R
|
import org.mosad.teapod.R
|
||||||
import org.mosad.teapod.databinding.PlayerLanguageSettingsBinding
|
import org.mosad.teapod.databinding.PlayerLanguageSettingsBinding
|
||||||
import org.mosad.teapod.ui.activity.player.PlayerViewModel
|
import org.mosad.teapod.ui.activity.player.PlayerViewModel
|
||||||
|
import org.mosad.teapod.util.hideBars
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
// TODO port to DialogFragment
|
class LanguageSettingsDialogFragment : DialogFragment() {
|
||||||
class LanguageSettingsPlayer @JvmOverloads constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null,
|
|
||||||
defStyleAttr: Int = 0,
|
|
||||||
model: PlayerViewModel? = null
|
|
||||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
private val binding = PlayerLanguageSettingsBinding.inflate(LayoutInflater.from(context), this, true)
|
private lateinit var model: PlayerViewModel
|
||||||
var onViewRemovedAction: (() -> Unit)? = null
|
private lateinit var binding: PlayerLanguageSettingsBinding
|
||||||
|
|
||||||
private var selectedLocale = model?.currentLanguage ?: Locale.ROOT
|
private var selectedLocale = Locale.ROOT
|
||||||
|
|
||||||
init {
|
companion object {
|
||||||
model?.let { m ->
|
const val TAG = "LanguageSettingsDialogFragment"
|
||||||
m.currentPlayback.streams.adaptive_hls.keys.forEach { languageTag ->
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setStyle(STYLE_NO_TITLE, R.style.FullScreenDialogStyle)
|
||||||
|
model = ViewModelProvider(requireActivity())[PlayerViewModel::class.java]
|
||||||
|
selectedLocale = model.currentLanguage
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
binding = PlayerLanguageSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
model.currentPlayback.streams.adaptive_hls.keys.forEach { languageTag ->
|
||||||
val locale = Locale.forLanguageTag(languageTag)
|
val locale = Locale.forLanguageTag(languageTag)
|
||||||
addLanguage(locale, locale == m.currentLanguage) { v ->
|
addLanguage(locale, locale == model.currentLanguage) { v ->
|
||||||
selectedLocale = locale
|
selectedLocale = locale
|
||||||
updateSelectedLanguage(v as TextView)
|
updateSelectedLanguage(v as TextView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
binding.buttonCloseLanguageSettings.setOnClickListener { close() }
|
binding.buttonCloseLanguageSettings.setOnClickListener { dismiss() }
|
||||||
binding.buttonCancel.setOnClickListener { close() }
|
binding.buttonCancel.setOnClickListener { dismiss() }
|
||||||
binding.buttonSelect.setOnClickListener {
|
binding.buttonSelect.setOnClickListener {
|
||||||
model?.setLanguage(selectedLocale)
|
model.setLanguage(selectedLocale)
|
||||||
close()
|
dismiss()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addLanguage(locale: Locale, isSelected: Boolean, onClick: OnClickListener) {
|
// initially hide the status and navigation bar
|
||||||
|
hideBars(requireDialog().window, binding.root)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDismiss(dialog: DialogInterface) {
|
||||||
|
super.onDismiss(dialog)
|
||||||
|
model.player.play()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addLanguage(locale: Locale, isSelected: Boolean, onClick: View.OnClickListener) {
|
||||||
val text = TextView(context).apply {
|
val text = TextView(context).apply {
|
||||||
height = 96
|
height = 96
|
||||||
gravity = Gravity.CENTER_VERTICAL
|
gravity = Gravity.CENTER_VERTICAL
|
||||||
|
@ -83,12 +104,11 @@ class LanguageSettingsPlayer @JvmOverloads constructor(
|
||||||
setPadding(75, 0, 0, 0)
|
setPadding(75, 0, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set selected to selected style
|
// set selected to selected style
|
||||||
selected.apply {
|
selected.apply {
|
||||||
setTextColor(context.resources.getColor(R.color.exo_white, context.theme))
|
setTextColor(context.resources.getColor(R.color.player_white, context.theme))
|
||||||
setTypeface(null, Typeface.BOLD)
|
setTypeface(null, Typeface.BOLD)
|
||||||
setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_baseline_check_24, 0, 0, 0)
|
setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_baseline_check_24, 0, 0, 0)
|
||||||
setPadding(0, 0, 0, 0)
|
setPadding(0, 0, 0, 0)
|
||||||
|
@ -96,10 +116,4 @@ class LanguageSettingsPlayer @JvmOverloads constructor(
|
||||||
compoundDrawablePadding = 12
|
compoundDrawablePadding = 12
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun close() {
|
|
||||||
(this.parent as ViewGroup).removeView(this)
|
|
||||||
onViewRemovedAction?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,9 +5,6 @@ import android.app.ActivityManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.view.View
|
|
||||||
import android.view.WindowInsets
|
|
||||||
import android.view.WindowInsetsController
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
|
@ -31,28 +28,7 @@ fun FragmentActivity.showFragment(fragment: Fragment) {
|
||||||
* hide the status and navigation bar
|
* hide the status and navigation bar
|
||||||
*/
|
*/
|
||||||
fun Activity.hideBars() {
|
fun Activity.hideBars() {
|
||||||
window.apply {
|
hideBars(window, window.decorView.rootView)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
||||||
setDecorFitsSystemWindows(false)
|
|
||||||
insetsController?.apply {
|
|
||||||
hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars())
|
|
||||||
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")
|
|
||||||
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
||||||
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
||||||
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.isInPiPMode(): Boolean {
|
fun Activity.isInPiPMode(): Boolean {
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package org.mosad.teapod.util
|
package org.mosad.teapod.util
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.Window
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import org.mosad.teapod.parser.crunchyroll.Collection
|
import org.mosad.teapod.parser.crunchyroll.Collection
|
||||||
import org.mosad.teapod.parser.crunchyroll.ContinueWatchingItem
|
import org.mosad.teapod.parser.crunchyroll.ContinueWatchingItem
|
||||||
import org.mosad.teapod.parser.crunchyroll.Item
|
import org.mosad.teapod.parser.crunchyroll.Item
|
||||||
|
@ -50,3 +55,13 @@ fun Locale.toDisplayString(fallback: String): String {
|
||||||
fallback
|
fallback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hideBars(window: Window?, root: View) {
|
||||||
|
if (window != null) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
WindowInsetsControllerCompat(window, root).let { controller ->
|
||||||
|
controller.hide(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.navigationBars())
|
||||||
|
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
android:layout_height="70dp"
|
android:layout_height="70dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
app:indicatorColor="@color/exo_white"
|
app:indicatorColor="@color/player_white"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
android:textColor="@android:color/primary_text_light"
|
android:textColor="@android:color/primary_text_light"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:backgroundTint="@color/exo_white"
|
app:backgroundTint="@color/player_white"
|
||||||
app:iconGravity="textStart" />
|
app:iconGravity="textStart" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
@ -100,7 +100,7 @@
|
||||||
android:textColor="@android:color/primary_text_light"
|
android:textColor="@android:color/primary_text_light"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:backgroundTint="@color/exo_white"
|
app:backgroundTint="@color/player_white"
|
||||||
app:iconGravity="textStart" />
|
app:iconGravity="textStart" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -37,7 +37,7 @@
|
||||||
android:layout_marginEnd="44dp"
|
android:layout_marginEnd="44dp"
|
||||||
android:text="@string/subtitles"
|
android:text="@string/subtitles"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textColor="@color/exo_white"
|
android:textColor="@color/player_white"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
android:layout_marginEnd="7dp"
|
android:layout_marginEnd="7dp"
|
||||||
android:text="@string/cancel"
|
android:text="@string/cancel"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:textColor="@color/exo_white"
|
android:textColor="@color/player_white"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:backgroundTint="@color/buttonBackgroundLight"
|
app:backgroundTint="@color/buttonBackgroundLight"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
<color name="buttonBackgroundDark">#ffffff</color>
|
<color name="buttonBackgroundDark">#ffffff</color>
|
||||||
<color name="controlHighlightDark">#11ffffff</color>
|
<color name="controlHighlightDark">#11ffffff</color>
|
||||||
|
|
||||||
|
<!-- player colors -->
|
||||||
|
<color name="player_white">#ffffff</color>
|
||||||
|
|
||||||
<color name="ic_launcher_background">#ffffff</color>
|
<color name="ic_launcher_background">#ffffff</color>
|
||||||
<color name="ic_splash_background">#ffffff</color>
|
<color name="ic_splash_background">#ffffff</color>
|
||||||
</resources>
|
</resources>
|
|
@ -86,4 +86,13 @@
|
||||||
<item name="android:popupBackground">?themeSecondary</item>
|
<item name="android:popupBackground">?themeSecondary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="FullScreenDialogStyle" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
<item name="android:windowFullscreen">true</item>
|
||||||
|
<item name="android:windowActionBar">false</item>
|
||||||
|
<item name="android:windowIsFloating">false</item>
|
||||||
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in New Issue