ananas/app/phone/src/main/java/dev/jdtech/jellyfin/BasePlayerActivity.kt
Cd16d d28e80d68e
feat: picture-in-picture (#277)
* add pip

* fixed OnResume() OnStop()
add picture in picture button
add pip settings

* fixed sourceRectHint
add aspectRatio

* fix import

* improve hide playerControls

* add onNewIntent()

* Home button/gesture settings

* add summary

* add GESTURE_EXCLUSION_AREA_SIDE

* remove if else in sourceRectHint
fix onStop() behavior

* fix behavior when using pip button, now go home

* test

* fix onStop()

* fix: mpv aspect ratio

* fix when in PiP mode and starting new playback

* refactor: pip implementation

Remove option to disable pip button, always show the button when pip is supported
Remove the option to completely disable pip
Format using ktlint

* fix when in pip mode and play a new video

* fix recent app behavior

* lint

* Some adjustments

* fix: Aspect ratio is too extreme

* fix: Activity recreation

* fix merge issues

* fix merge issues

* ktlintFormat

* Add Picture in Picture

* fix

* fix sourceRectHint, updateZoomMode before entering pip

* lint

* fix: disable pip when player is locked

* lint

* lint

* fix: sourceRectHint

* fix: replace media items in mpv

* fix: don't show skip intro button in pip

* chore: remove `android:resizeableActivity` from manifest since the default is already `true`

* refactor: remove option to force 16:9 aspect ratio

* refactor: update strings

---------

Co-authored-by: Jarne Demeulemeester <jarnedemeulemeester@gmail.com>
2023-08-14 22:47:42 +02:00

100 lines
3 KiB
Kotlin

package dev.jdtech.jellyfin
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.updatePadding
import androidx.media3.exoplayer.trackselection.MappingTrackSelector
import androidx.media3.session.MediaSession
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
abstract class BasePlayerActivity : AppCompatActivity() {
abstract val viewModel: PlayerActivityViewModel
private lateinit var mediaSession: MediaSession
private var wasPip: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
}
override fun onStart() {
super.onStart()
mediaSession = MediaSession.Builder(this, viewModel.player).build()
}
override fun onResume() {
super.onResume()
if (wasPip) {
wasPip = false
} else {
viewModel.player.playWhenReady = viewModel.playWhenReady
}
hideSystemUI()
}
override fun onPause() {
super.onPause()
if (isInPictureInPictureMode) {
wasPip = true
} else {
viewModel.playWhenReady = viewModel.player.playWhenReady == true
viewModel.player.playWhenReady = false
}
}
override fun onStop() {
super.onStop()
mediaSession.release()
if (wasPip) {
finish()
}
}
protected fun hideSystemUI() {
WindowCompat.getInsetsController(window, window.decorView).apply {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(WindowInsetsCompat.Type.systemBars())
}
window.attributes.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
protected fun isRendererType(
mappedTrackInfo: MappingTrackSelector.MappedTrackInfo,
rendererIndex: Int,
type: Int,
): Boolean {
val trackGroupArray = mappedTrackInfo.getTrackGroups(rendererIndex)
if (trackGroupArray.length == 0) {
return false
}
val trackType = mappedTrackInfo.getRendererType(rendererIndex)
return type == trackType
}
protected fun configureInsets(playerControls: View) {
playerControls.setOnApplyWindowInsetsListener { _, windowInsets ->
val cutout = windowInsets.displayCutout
playerControls.updatePadding(
left = cutout?.safeInsetLeft ?: 0,
top = cutout?.safeInsetTop ?: 0,
right = cutout?.safeInsetRight ?: 0,
bottom = cutout?.safeInsetBottom ?: 0,
)
return@setOnApplyWindowInsetsListener windowInsets
}
}
}